Problem:
デッドロックを検出せよ
コンピュータにおける「データベース」とは、情報を管理するための入れ物で、「データベースマネジメントシステム(DBMS)」とは、その管理をする仕組みです。複数のユーザが利用するデータベースでは、DBMS は慎重に構築する必要があります。
例えば、倉庫から商品を１つ取り出した人が、データベースに対して以下の処理を行うとしましょう。
(1) 商品の個数
N
をデータベースから読む。
(2) 新たな商品の個数
N
-1 をデータベースに書き込む。
ユーザ１が(1)を終えて(2)を始める前に、別のユーザ２が倉庫から商品を取り出して(1)を行ったとします。ユーザ２もユーザ１と同じ個数を読むので、２人が(2)を終えたときには商品は２個減るのにデータベース上では１個しか減らないというおかしな結果になります。このような問題を防ぐために、DBMS は特定のデータを操作中のユーザに、そのデータを「ロック」する権利を与えます。ロックされていれば、他のユーザはその値を操作できなくなるので、おかしな結果を返すことはなくなります。
これで安全に操作できることは保証されますが、今度は別の問題が起こります。例えば、ユーザ１とユーザ２が以下のような順番でデータＡとＢをロックしようとしたらどうなるでしょうか？
(1) ユーザ１がデータＡのロックを試みる → 成功（データＡがロック中になる）
(2) ユーザ２がデータＢのロックを試みる → 成功（データＢがロック中になる）
(3) ユーザ１がデータＢのロックを試みる → データＢがロック中なのでユーザ１は待つ
(4) ユーザ２がデータＡのロックを試みる → データＡがロック中なのでユーザ２は待つ
(4)を実行した時点では、ユーザ１がＡ、ユーザ２がＢをロックしているので、(3)(4)は永久に成功しませ
ん。これを「デッドロック」と呼びます。DBMS はこれを検出しなければなりません。
ある時点でデッドロックが起きているかどうかは、その時点でのすべてのユーザとデータの依存関係を書き、循環ができているかどうかで判断できます。依存関係は，ユーザがデータをロック済みの場合はデータからユーザの向きに矢印を、ユーザがデータのロックを試行していて待ち状態になっている場合はユーザからデータの向きに矢印を書くことで表します。
上の(1)から(4)の例であれば、(4)を実行した時点での依存関係は右上のような図になります。このとき、矢印の方向に進むと、ユーザ１→データＢ→ユーザ２→データＡ→ユーザ１という循環ができているため、デッドロックが起きていることがわかります。DBMS の苦労を体験するため、あなたにここでやってもらいたいのは、このようなデッドロックを検出するプログラムを作成することです。
入力
入力は以下の形式で与えられる。
N
rel
1
rel
2
:
rel
N
１行目にユーザとデータの依存関係の数
N
(1 ≤
N
≤ 1000) が与えられる。続く
N
行に、ユーザとデータの依存関係
rel
i
が与えられる。依存関係は lock と wait の２種類あり、各
rel
i
は以下のいずれかの形式で与えられる。
u lock d
または
u wait d
u lock d
は、ユーザ
u
(1 ≤
u
≤ 100) が、データ
d
(1 ≤
d
≤ 100) をロック済みであることを表す。
u wait d
は、ユーザ
u
(1 ≤
u
≤ 100) が、データ
d
(1 ≤
d
≤ 100) のロックを試行していて待ち状態であることを表す。
ただし、入力は以下の条件を満たしていると仮定してよい。
ロックされていないデータに対して、ユーザが待ち状態ではない。
二人以上のユーザにロックされているデータはない。
ユーザ自身がロックしているデータに対して、待ち状態ではない。
同じ依存関係は与えられない。
出力
デッドロックが発生しているなら 1、発生していないなら 0 を１行に出力する。
入出力例
入力例１
4
1 lock 1
2 lock 2
1 wait 2
2 wait 1
出力例１
1
入力例２
4
3 lock 3
2 wait 3
3 lock 4
2 wait 4
出力例２
0

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;

#define MAX_V 10000000
#define MAX_E 10000000
#define INF 1111111111
struct edge{int from,to,cost;};

edge es[MAX_E]; 
int d[MAX_V]; 
int V=202,E;

bool find_negative_loop(){
  memset(d,0,sizeof(d));
  for(int i=0;i<V;i++){
    for(int j=0;j<E;j++){
      edge e=es[j];
      if(d[e.to]>d[e.from]+e.cost){
	d[e.to]=d[e.from]+e.cost;
	if(i==V-1)return true;
      }
    }
  }  
  return false;
}


signed main(){
  cin>>E;
  for(int i=0;i<E;i++){
    int u,d;
    string a;
    cin>>u>>a>>d;
    if(a[0]=='w')es[i]=(edge){u,d+101,-1};
    else es[i]=(edge){d+101,u,-1};
  }
  cout<<find_negative_loop()<<endl;
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 42280
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> P;

#define pb push_back
#define rep(i, a, n) for(int i = (a); i < (n); i++)
#define dep(i, a, n) for(int i = (a); i >= (n); i--)
#define mod 1e9+7

__attribute__((constructor))
void initial() {
  cin.tie(0);
  ios::sync_with_stdio(false);
}

int n;
vector<int> u[101];
int d[101];
int f = 0;

void solve(int i, int m, map<int, int> loopU, map<int, int> loopD) {
  if(f) return;
  if(m == 0) {
    if(loopD[i]) {
      f = 1;
      return;
    }
    loopD[i] = 1;
    if(d[i]) solve(d[i], !m, loopU, loopD);
  }else {
    if(loopU[i]) {
      f = 1;
      return;
    }
    loopU[i] = 1;
    rep(j, 0, u[i].size()) {
      solve(u[i][j], !m, loopU, loopD);
    }
  }
}

int main() {
  cin >> n;
  rep(i, 0, n) {
    int a, b;
    string s;
    cin >> a >> s >> b;
    if(s[0] == 'l') {
      d[b] = a;
    }else {
      u[a].pb(b);
    }
  }
  rep(i, 1, 101) {
    if(d[i]) {
      map<int, int> a, b;
      solve(i, 0, a, b);
    }
  }
  rep(i, 1, 101) {
    if(u[i].size() > 0) {
      map<int, int> a, b;
      solve(i, 1, a, b);
    }
  }
  cout << f << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 4152
final_rank: 6

code_snippet: #include <bits/stdc++.h>
#define r(i,n) for(int i=0;i<n;i++)
using namespace std;
int n,d[222][222],f,a,b;
string s;
main(){
    cin>>n;
    r(i,222)r(j,222)d[i][j]=(i==j?0:1e8);
    while(n--){
        cin>>a>>s>>b;
        if(s=="lock")d[a][b+111]=-1;
        else d[b+111][a]=-1;
    }
    r(o,222)r(i,222)r(j,222)d[i][j]=min(d[i][j],d[i][o]+d[o][j]);
    r(i,222)if(d[i][i]<0)f++;
    cout<<(f?1:0)<<endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3380
final_rank: 5

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;

int mincost[200][200];
int main() {
	for (int i = 0; i < 200; i++)fill(mincost[i], mincost[i] + 200, 1 << 29);
	int a; cin >> a;
	for (int b = 0; b < a; b++) {
		int c, e; string d;
		cin >> c >> d >> e; c--; e=e+99;
		if (d[0] == 'l') {
			mincost[e][c] = 0;
		}
		else {
			mincost[c][e] = 0;
		}
	}
	for (int c = 0; c < 200; c++) {
		for (int d = 0; d < 200; d++) {
			for (int e = 0; e < 200; e++) {
				mincost[d][e] = min(mincost[d][e], mincost[d][c] + mincost[c][e]);
			}
		}
	}
	bool S = false;
	for (int i = 0; i < 200; i++) {
		if (mincost[i][i] == 0)S = true;
	}
	cout << S << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3328
final_rank: 3

code_snippet: #include <iostream>

using namespace std;

constexpr int MAX = 200;
constexpr int INF = (1 << 29);

int main()
{
    int N, u, v, d[MAX][MAX];
    string s;

    for (int i = 0; i < MAX; i++) {
        for (int j = 0; j < MAX; j++) {
            d[i][j] = (i != j) * INF;
        }
    }
    
    cin >> N;    
    for (int i = 0; i < N; i++) {
        cin >> u >> s >> v;
        u--; v--; v += MAX / 2;
        if (s == "lock") swap(u, v);
        d[u][v] = -1;
    }

    for (int k = 0; k < MAX; k++) {
        for (int i = 0; i < MAX; i++) {
            for (int j = 0; j < MAX; j++) {
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
            }
        }
    }
    
    bool res = 0;
    for (int i = 0; i < MAX; i++) {
        if (d[i][i] < 0) {
            res = 1;
            break;
        }
    }
    cout << res << endl;    
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3348
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef long long ll;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define each(itr,c) for(__typeof(c.begin()) itr=c.begin(); itr!=c.end(); ++itr)
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second

int l[100][100]={0}, w[100][100]={0};

int main()
{
    int n;
    scanf(" %d", &n);
    rep(i,n)
    {
        int u,d;
        char s[10];
        scanf(" %d %s %d", &u, s, &d);
        --u;
        --d;

        if(s[0]=='l') l[u][d]=1;
        else w[u][d]=1;
    }

    int ans=0;
    rep(a,100)rep(b,a)
    {
        rep(i,100)rep(j,100)
        {
            if(i==j) continue;
            if(l[a][i] && w[a][j] && l[b][j] && w[b][i]) ans=1;
        }
    }
    printf("%d\n", ans);
    return 0;
}
accuracy: 0.3
time_ms: 30
memory_kb: 3208
final_rank: 10

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <functional>
#include <numeric>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#include <sstream>
#include <complex>
#include <fstream>

using namespace std;

#define FOR(i,a,b) for(long long i=(a);i<(b);i++)
#define REP(i,N) for(long long i=0;i<(N);i++)
#define ALL(s) (s).begin(),(s).end()
#define fi first
#define se second

#define PI acos(-1.0)
#define INF 10e15+9
#define MOD 1000000007
#define EPS 1e-10
#define MAX_N 100100
#define MAX_M 100100

typedef long long ll;
typedef pair<ll, ll> P;
typedef pair<double, double> PD;
typedef pair<string, ll> PS;
typedef vector<ll> V;
typedef pair<P, char> PC;

int n;
int u, d;
string rel;
vector<int> data[110];
int user[110];
bool ans = 0;

void check(bool mode, int num, int search){
	//cout << num << endl;
	if (mode == 0){
		check(1, user[num], search);
	}
	else{
		if (data[num].size() == 0)return;
		REP(i, data[num].size()){
			if (data[num][i] == search){
				ans = 1;
				return;
			}
			check(0, data[num][i], search);
		}
	}
}

int main(){
	cin >> n;
	REP(i, n){
		cin >> u >> rel >> d;
		if (rel == "lock"){
			data[d].push_back(u);
		}
		else{
			user[u] = d;
		}
	}

	FOR(i, 1, 101){
		if (user[i])check(1, user[i], i);
	}

	if (ans)cout << 1 << endl;
	else cout << 0 << endl;
}
accuracy: 0.2
time_ms: 10
memory_kb: 19344
final_rank: 12

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <functional>
#include <numeric>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#include <sstream>
#include <complex>
#include <fstream>

using namespace std;

#define FOR(i,a,b) for(long long i=(a);i<(b);i++)
#define REP(i,N) for(long long i=0;i<(N);i++)
#define ALL(s) (s).begin(),(s).end()
#define fi first
#define se second

#define PI acos(-1.0)
#define INF 10e15+9
#define MOD 1000000007
#define EPS 1e-10
#define MAX_N 100100
#define MAX_M 100100

typedef long long ll;
typedef pair<ll, ll> P;
typedef pair<double, double> PD;
typedef pair<string, ll> PS;
typedef vector<ll> V;
typedef pair<P, char> PC;

int n;
int u, d;
string rel;
bool lock[110][110], wait[110][110];

int main(){
	cin >> n;
	REP(i, n){
		cin >> u >> rel >> d;
		if (rel == "lock"){
			lock[u][d] = 1;
		}
		else{
			wait[u][d] = 1;
		}
	}
	FOR(i,1, 101){
		FOR(j,1, 101){
			FOR(k,1, 101){
				FOR(l, 1, 101){
					if (lock[i][j] && lock[k][l]){
						if (wait[i][l] && wait[k][j]){
							cout << 1 << endl;
							return 0;
						}
					}
				}
			}
		}
	}
	cout << 0 << endl;
}
accuracy: 0.3
time_ms: 70
memory_kb: 1216
final_rank: 11

code_snippet: #include<iostream>
#include<vector>
#include<string>
#include<queue>
using namespace std;
vector<int>G[240]; int dist[240];
int main() {
	int n; cin >> n;
	for (int i = 0; i < n; i++) {
		int a, b; string S;
		cin >> a >> S >> b; a--; b--;
		if (S == "wait") { G[a].push_back(b + 120); }
		if (S == "lock") { G[b + 120].push_back(a); }
	}
	int C = 0;
	for (int i = 0; i < 240; i++) {
		queue<int>Q;
		for (int j = 0; j < 240; j++)dist[j] = 0;
		Q.push(i); int cnt = 0;
		while (!Q.empty()) {
			cnt++; int a1 = Q.front(); Q.pop();
			if (cnt >= 100000) { C = 1; break; }
			for (int j = 0; j < G[a1].size(); j++) {
				if (dist[G[a1][j]]>dist[a1] - 1) {
					dist[G[a1][j]] = dist[a1] - 1;
					Q.push(G[a1][j]);
				}
			}
		}
	}
	cout << C << endl;
	return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 1248
final_rank: 8

code_snippet: #include <iostream>
#include <vector>
#include <map>
#define M 201
using namespace std;
typedef pair<int,int> P;
void func(int);
int N,u,d;
vector<int> node;
bool edge[M][M],ans;
map<P,bool> visited;
string s;

int main(){
  cin>>N;
  for(int i=0;i<M;i++)
    for(int j=0;j<M;j++) edge[i][j]=false;
  while(N--){
    cin>>u>>s>>d;
    node.push_back(u);
    if(s=="lock") edge[u][d+100]=true;
    else edge[d+100][u]=true;
  }
  for(int i=0;i<(int)node.size();i++){
    func(node[i]);
    if(ans) break;
    visited.clear();
  }
  if(ans) cout<<1<<endl;
  else cout<<0<<endl;
  return 0;
}

void func(int x){
  if(ans) return ;
  for(int i=0;i<M;i++){
    if(edge[x][i]){
      if(visited.find(make_pair(x,i))!=visited.end()&&visited[make_pair(x,i)]==true){
	ans=true;
	break;
      }
      visited[make_pair(x,i)]=true;
      func(i);
    }
  }
}
accuracy: 0.75
time_ms: 20
memory_kb: 1328
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;
const int INF = 1 << 28;

int main()
{
  int N;
  int graph[200][200];
  fill_n(*graph, 200 * 200, INF);
  for(int i = 0; i < 200; i++) graph[i][i] = 0;

  cin >> N;
  while(N--) {
    int u, d;
    string type;
    cin >> u >> type >> d;
    --u, --d;
    if(type == "lock") graph[100 + d][u] = -1;
    else graph[u][100 + d] = -1;
  }
  for(int k = 0; k < 200; k++) {
    for(int i = 0; i < 200; i++) {
      for(int j = 0; j < 200; j++) {
        graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j]);
      }
    }
  }
  bool flag = false;
  for(int i = 0; i < 200; i++) {
    flag |= graph[i][i] < 0;
  }
  cout << flag << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 1364
final_rank: 2

code_snippet: #include<stdio.h>
#include<algorithm>
using namespace std;
int g[210][210];
char in[10];
int main(){
	int a;scanf("%d",&a);
	for(int i=0;i<200;i++)g[i][i]=1;
	for(int i=0;i<a;i++){
		int p,q;scanf("%d%s%d",&p,in,&q);
		p--;q--;
		if(in[0]=='l')g[p][q+100]=1;
		else g[q+100][p]=1;
	}
	for(int k=0;k<200;k++)for(int i=0;i<200;i++)for(int j=0;j<200;j++){
		if(g[i][k]&&g[k][j])g[i][j]=1;
	}
	for(int i=0;i<200;i++)for(int j=i+1;j<200;j++){
		if(g[i][j]&&g[j][i]){printf("1\n");return 0;}
	}
	printf("0\n");
}
accuracy: 1
time_ms: 10
memory_kb: 1176
final_rank: 1