Problem:
Problem H:
Company Organization
You started a company a few years ago and fortunately it has been highly successful. As the growth of the company, you noticed that you need to manage employees in a more organized way, and decided to form several groups and assign employees to them.
Now, you are planning to form n groups, each of which corresponds to a project in the company. Sometimes you have constraints on members in groups. For example, a group must be a subset of another group because the former group will consist of senior members of the latter group, the members in two groups must be the same because current activities of the two projects are closely related, the members in two groups must not be exactly the same to avoid corruption, two groups cannot have a common employee because of a security reason, and two groups must have a common employee to facilitate collaboration.
In summary, by letting
X
i
(
i
= 1, ... ,
n
) be the set of employees assigned to the
i
-th group, we have five types of constraints as follows.
X
i
⊆
X
j
X
i
=
X
j
X
i
≠
X
j
X
i
∩
X
j
= ∅
X
i
∩
X
j
≠ ∅
Since you have listed up constraints without considering consistency, it might be the case that you cannot satisfy all the constraints. Constraints are thus ordered according to their priorities, and you now want to know how many constraints of the highest priority can be satisfied.
You do not have to take ability of employees into consideration. That is, you can assign anyone to any group. Also, you can form groups with no employee. Furthermore, you can hire or fire as many employees as you want if you can satisfy more constraints by doing so.
For example, suppose that we have the following five constraints on three groups in the order of their priorities, corresponding to the first dataset in the sample input.
X
2
⊆
X
1
X
3
⊆
X
2
X
1
⊆
X
3
X
1
≠
X
3
X
3
⊆
X
1
By assigning the same set of employees to
X
1
,
X
2
, and
X
3
, we can satisfy the first three constraints. However, no matter how we assign employees to
X
1
,
X
2
, and
X
3
, we cannot satisfy the first four highest priority constraints at the same time. Though we can satisfy the first three constraints and the fifth constraint at the same time, the answer should be three.
Input
The input consists of several datasets. The first line of a dataset consists of two integers
n
(2 ≤
n
≤ 100) and
m
(1 ≤
m
≤ 10000), which indicate the number of groups and the number of constraints, respectively. Then, description of
m
constraints follows. The description of each constraint consists of three integers
s
(1 ≤
s
≤ 5),
i
(1 ≤
i
≤
n
), and
j
(1 ≤
j
≤
n
,
j
≠=
i
), meaning a constraint of the
s
-th type imposed on the
i
-th group and the
j
-th group. The type number of a constraint is as listed above. The constraints are given in the descending order of priority.
The input ends with a line containing two zeros.
Output
For each dataset, output the number of constraints of the highest priority satisfiable at the same time.
Sample 
...(truncated)

Submitted solutions:

code_snippet: #include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>

using namespace std;

const int MAXN = 1e4+10;
const int MAXG = 110;

int n,m;
int x[MAXN],op[MAXN],y[MAXN];

int f[MAXG][MAXG],g[MAXG][MAXG];
bool check(int mid) {
    for (int i=1; i<=n; i++)
        for (int j=1; j<=n; j++)
            f[i][j] = 0 ;
    for (int i=1; i<=n; i++) {
        for (int j=1; j<=n; j++) g[i][j]=0;
        g[i][i]=1;
    }
    for (int Q=1; Q<=mid; Q++) {
        int i = x[Q] , j = y[Q] , ope = op[Q];
        if (ope==1) g[i][j] = 1 ;
        else if (ope==2) g[i][j] = g[j][i] = 1 ;
        else if (ope==4) f[i][j] = f[j][i] = 1 ;
    }
    for (int k = 1 ; k <= n ; k++)
        for (int i = 1 ; i <= n ; i++)
            for (int j = 1 ; j <= n ; j++)
                if (g[i][k] && g[k][j]) g[i][j] = 1 ;

    for (int k = 1 ; k <= n ; k++)
        for (int i = 1 ; i <= n ; i++)
            for (int j = 1 ; j <= n ; j++)
                if (f[i][k] && g[j][k]) f[i][j] = f[j][i] = 1 ;

    for (int Q = 1 ; Q <= mid ; Q++) {
        int i = x[Q] , j = y[Q] , ope = op[Q];
        if (ope==3) {
            if (f[i][i] && f[j][j]) return false ;
            if (g[i][j] && g[j][i]) return false ;
        } else if (ope==5) {
            if (f[i][j] || f[j][i] || f[i][i] || f[j][j]) return false ;
        }
    }
    return true ;
}

int main() {
    while (~scanf("%d%d",&n,&m) && (n+m)) {
        for (int i=1; i<=m; i++) scanf("%d%d%d",&op[i],&x[i],&y[i]);
        int l=1,r=m,ans=0;
        while (l<=r) {
            int mid=l+r>>1;
            if (check(mid)) {
                ans=mid;
                l=mid+1;
            } else r=mid-1;
        }
        printf("%d\n",ans);
    }
    return 0;
}
accuracy: 1
time_ms: 360
memory_kb: 3628
final_rank: 10

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

struct info {
	int t, a, b;
};

bool solve(int N, int M, const vector<info>& I) {
	vector<vector<bool> > adj(N, vector<bool>(N, false));
	for (info s : I) {
		if (s.t == 1) {
			adj[s.a][s.b] = true;
		}
		if (s.t == 2) {
			adj[s.a][s.b] = true;
			adj[s.b][s.a] = true;
		}
	}
	vector<vector<bool> > reach = adj;
	for (int i = 0; i < N; i++) {
		reach[i][i] = true;
	}
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			for (int k = 0; k < N; k++) {
				if (reach[j][i] && reach[i][k]) {
					reach[j][k] = true;
				}
			}
		}
	}
	vector<vector<bool> > sameval(N, vector<bool>(N, false));
	vector<int> empty(N, -1);
	for (info s : I) {
		if (s.t == 4) {
			for (int i = 0; i < N; i++) {
				if (reach[i][s.a] && reach[i][s.b]) {
					if (empty[i] == 0) {
						return false;
					}
					empty[i] = 1;
				}
			}
		}
		if (s.t == 5) {
			for (int i = 0; i < N; i++) {
				if (reach[s.a][i] || reach[s.b][i]) {
					if (empty[i] == 1) {
						return false;
					}
					empty[i] = 0;
				}
			}
		}
	}
	for (info s : I) {
		if (s.t == 5) {
			vector<int> v;
			for (int i = 0; i < N; i++) {
				if (reach[s.a][i] || reach[s.b][i]) {
					v.push_back(i);
				}
			}
			for (int i : v) {
				for (int j : v) {
					sameval[i][j] = true;
				}
			}
		}
	}
	for (info s : I) {
		if (s.t == 3 && ((reach[s.a][s.b] && reach[s.b][s.a]) || (empty[s.a] == 1 && empty[s.b] == 1))) {
			return false;
		}
		if (s.t == 4 && sameval[s.a][s.b]) {
			return false;
		}
	}
	return true;
}

int main() {
	while (true) {
		int N, M;
		cin >> N >> M;
		if (N == 0 && M == 0) {
			break;
		}
		vector<info> I(M);
		for (int i = 0; i < M; i++) {
			cin >> I[i].t >> I[i].a >> I[i].b;
			I[i].a -= 1;
			I[i].b -= 1;
		}
		int l = 0, r = M + 1;
		while (r - l > 1) {
			int m = (l + r) / 2;
			vector<info> J(I.begin(), I.begin() + m);
			if (solve(N, M, J)) {
				l = m;
			}
			else {
				r = m;
			}
		}
		cout << l << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 3620
final_rank: 9

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

class unionfind {
private:
	int n;
	vector<int> par;
public:
	unionfind() : n(0), par(vector<int>()) {}
	unionfind(int n_) : n(n_) {
		par.resize(n);
		for (int i = 0; i < n; i++) {
			par[i] = i;
		}
	}
	int root(int x) {
		if (x == par[x]) {
			return x;
		}
		return par[x] = root(par[x]);
	}
	void link(int x, int y) {
		x = root(x);
		y = root(y);
		par[y] = x;
	}
	bool connected(int x, int y) {
		return root(x) == root(y);
	}
};

struct info {
	int t, a, b;
};

bool solve_dag(int N, int M, const vector<info>& I) {
	vector<vector<bool> > adj(N, vector<bool>(N, false));
	for (info s : I) {
		if (s.t == 1) {
			adj[s.a][s.b] = true;
		}
	}
	vector<vector<bool> > reach = adj;
	for (int i = 0; i < N; i++) {
		reach[i][i] = true;
	}
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			for (int k = 0; k < N; k++) {
				if (reach[j][i] && reach[i][k]) {
					reach[j][k] = true;
				}
			}
		}
	}
	vector<vector<bool> > sameval(N, vector<bool>(N, false));
	vector<int> empty(N, -1);
	for (info s : I) {
		if (s.t == 4) {
			for (int i = 0; i < N; i++) {
				if (reach[i][s.a] && reach[i][s.b]) {
					if (empty[i] == 0) {
						return false;
					}
					empty[i] = 1;
				}
			}
		}
		if (s.t == 5) {
			for (int i = 0; i < N; i++) {
				if (reach[s.a][i] || reach[s.b][i]) {
					if (empty[i] == 1) {
						return false;
					}
					empty[i] = 0;
				}
			}
		}
	}
	unionfind uf(N);
	for (info s : I) {
		if (s.t == 5) {
			vector<int> v;
			for (int i = 0; i < N; i++) {
				if (reach[s.a][i] || reach[s.b][i]) {
					v.push_back(i);
				}
			}
			for (int i : v) {
				for (int j : v) {
					sameval[i][j] = true;
				}
			}
		}
	}
	for (info s : I) {
		if (s.t == 3 && (s.a == s.b || (empty[s.a] == 1 && empty[s.b] == 1))) {
			return false;
		}
		if (s.t == 4 && sameval[s.a][s.b]) {
			return false;
		}
	}
	return true;
}

bool solve(int N, int M, const vector<info>& I) {
	vector<vector<bool> > adj(N, vector<bool>(N, false));
	for (info s : I) {
		if (s.t == 1) {
			adj[s.a][s.b] = true;
		}
		if (s.t == 2) {
			adj[s.a][s.b] = true;
			adj[s.b][s.a] = true;
		}
	}
	vector<bool> vis(N, false);
	vector<int> ord;
	auto dfs1 = [&](auto& self, int pos) -> void {
		vis[pos] = true;
		for (int i = 0; i < N; i++) {
			if (adj[pos][i] && !vis[i]) {
				self(self, i);
			}
		}
		ord.push_back(pos);
	};
	for (int i = N - 1; i >= 0; i--) {
		if (!vis[i]) {
			dfs1(dfs1, i);
		}
	}
	reverse(ord.begin(), ord.end());
	int counter = 0;
	vector<int> col(N, -1);
	auto dfs2 = [&](auto& self, int pos) -> void {
		col[pos] = counter;
		for (int i = 0; i < N; i++) {
			if (adj[i][pos] && col[i] == -1) {
				self(self, i);
			}
		}
	};
	for (int i : ord) {
		if (col[i] == -1) {
			dfs2(dfs2, i);
			counter += 1;
		}
	}
	vector<info> J;
	for (info s : I) {
		if (s.t == 1 && col[s.a] != col[s.b]) {
			J.push_back(info{1, col[s.a], col[s.b]});
		}
		if (s.t >= 3) {
			J.push_back(info{s.t, col[s.a], col[s.b]});
		}
	}
	return solve_dag(counter, J.size(), J);
}

int main() {
	while (true) {
		int N, M;
		cin >> N >> M;
		if (N == 0 && M == 0) {
			break;
		}
		vector<info> I(M);
		for (int i = 0; i < M; i++) {
			cin >> I[i].t >> I[i].a >> I[i].b;
			I[i].a -= 1;
			I[i].b -= 1;
		}
		int l = 0, r = M + 1;
		while (r - l > 1) {
			int m = (l + r) / 2;
			vector<info> J(I.begin(), I.begin() + m);
			if (solve(N, M, J)) {
				l = m;
			}
			else {
				r = m;
			}
		}
		cout << l << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 3716
final_rank: 8

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
//constexpr ll mod = 998244353;
constexpr ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	//if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);
template<typename T>
void addv(vector<T>& v, int loc, T val) {
	if (loc >= v.size())v.resize(loc + 1, 0);
	v[loc] += val;
}
/*const int mn = 100005;
bool isp[mn];
vector<int> ps;
void init() {
	fill(isp + 2, isp + mn, true);
	for (int i = 2; i < mn; i++) {
		if (!isp[i])continue;
		ps.push_back(i);
		for (int j = 2 * i; j < mn; j += i) {
			isp[j] = false;
		}
	}
}*/

//[,val)
template<typename T>
auto prev_itr(set<T>& st, T val) {
	auto res = st.lower_bound(val);
	if (res == st.begin())return st.end();
	res--; return res;
}

//[val,)
template<typename T>
auto next_itr(set<T>& st, T val) {
	auto res = st.lower_bound(val);
	return res;
}
using mP = pair<modint, modint>;


int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
//-----------------------------------------

struct graph {
private:
	int n;
	vector<vector<int>> G, rG;
	vector<bool> used;
	vector<int> vs;

	int mk;
	vector<vector<int>> fG;
	vector<vector<int>> ori;
	vector<int> trans;
public:
	graph(int sz) {
		n = sz;
		G.resize(n);
		rG.resize(n);
		used.resize(n);

		fG.resize(n);
		trans.resize(n, -1);
		ori.resize(n);
	}
	void add_edge(int a, int b) {
		G[a].push_back(b);
		rG[b].push_back(a);
	}
	void dfs(int v) {
		used[v] = true;
		rep(i, G[v].size()) {
			if (!used[G[v][i]])dfs(G[v][i]);
		}
		vs.push_back(v);
	}
	void rdfs(int v, int k) {
		used[v] = true;
		queue<int> q; q.push(v);
		vector<int> c;
		while (!q.empty()) {
			int id = q.front(); q.pop();
			ori[k].push_back(id);
			rep(j, rG[id].size()) {
				int to = rG[id][j];
				if (used[to]) {
					if (trans[to] >= 0)c.push_back(trans[to]);
					continue;
				}
				used[to] = true; q.push(to);
			}
		}
		sort(c.begin(), c.end());
		int len = unique(c.begin(), c.end()) - c.begin();
		rep(i, len) {
			fG[c[i]].push_back(k);
		}
		rep(i, ori[k].size()) {
			trans[ori[k][i]] = k;
		}
	}
	void scc() {
		fill(used.begin(), used.end(), false);
		rep(i, n) {
			if (!used[i])dfs(i);
		}
		fill(used.begin(), used.end(), false);
		int k = 0;
		per(i, (int)vs.size()) {
			if (!used[vs[i]]) {
				rdfs(vs[i], k); k++;
			}
		}
		mk = k;
	}
	bool eq(int a, int b) {
		return trans[a] == trans[b];
	}
	bool istwosat(int sup) {
		rep(i, sup)if (trans[i] == trans[i + sup])return false;
		return true;
	}
};

bool can[100][100];
bool ss[100][100];
int n, m;
void solve() {
	vector<int> typ(m), a(m), b(m);
	rep(i, m) {
		cin >> typ[i] >> a[i] >> b[i];
		a[i]--; b[i]--;
	}
	auto ok = [&](int c) {
		vector<vector<int>> G(n);
		rep(i, n)rep(j, n) {
			can[i][j] = false;
		}
		rep(i, c) {
			if (typ[i] == 1) {
				G[a[i]].push_back(b[i]);
			}
			else if (typ[i] == 2) {
				G[a[i]].push_back(b[i]);
				G[b[i]].push_back(a[i]);
			}
		}
		rep(i, n) {
			can[i][i] = true;
			queue<int> q; q.push(i);
			while (!q.empty()) {
				int id = q.front(); q.pop();
				for (int to : G[id]) {
					if (!can[i][to]) {
						can[i][to] = true;
						q.push(to);
					}
				}
			}
		}
		//equal check
		graph g(n);
		rep(i, c) {
			if (typ[i] == 1) {
				g.add_edge(a[i], b[i]);
			}
			else if (typ[i] == 2) {
				g.add_edge(a[i], b[i]);
				g.add_edge(b[i], a[i]);
			}
		}
		g.scc();
		rep(i, c)if (typ[i] == 3) {
			if (g.eq(a[i], b[i])) {
				return false;
			}
		}
		//2-sat about empty set
		graph st(2 * n);
		rep(i, c) {
			if (typ[i] == 1) {
				st.add_edge(b[i], a[i]);
				st.add_edge(a[i] + n, b[i] + n);
			}
			else if (typ[i] == 2) {
				st.add_edge(a[i], b[i]);
				st.add_edge(b[i], a[i]);
				st.add_edge(a[i] + n, b[i] + n);
				st.add_edge(b[i] + n, a[i] + n);
			}
			else if (typ[i] == 3) {
				st.add_edge(a[i], b[i] + n);
				st.add_edge(b[i], a[i] + n);
				if (can[a[i]][b[i]])st.add_edge(b[i], b[i] + n);
				if (can[b[i]][a[i]])st.add_edge(a[i], a[i] + n);
			}
			else if (typ[i] == 4) {
				if (can[a[i]][b[i]]) {
					st.add_edge(a[i] + n, a[i]);
				}
				if (can[b[i]][a[i]]) {
					st.add_edge(b[i] + n, b[i]);
				}
			}
			else if (typ[i] == 5) {
				st.add_edge(a[i], a[i] + n);
				st.add_edge(b[i], b[i] + n);
			}
		}
		
		//conflict between 4 and 5
		rep(i, n)rep(j, n) {
			ss[i][j] = false;
		}
		rep(i, c)if (typ[i] == 5) {
			ss[a[i]][b[i]] = ss[b[i]][a[i]] = true;
		}
		rep(i, n) {
			queue<int> q;
			rep(j, n) {
				if (ss[i][j]) {
					q.push(j);
				}
			}
			while (!q.empty()) {
				int id = q.front(); q.pop();
				for (int to : G[id]) {
					if (!ss[i][to]) {
						ss[i][to] = true;
						q.push(to);
					}
				}
			}
		}
		rep(j, n) {
			queue<int> q;
			rep(i, n)if (ss[i][j])q.push(i);
			while (!q.empty()) {
				int id = q.front(); q.pop();
				for (int to : G[id]) {
					if (!ss[to][j]) {
						ss[to][j] = true;
						q.push(to);
					}
				}
			}
		}
		rep(i, c)if (typ[i] == 4) {
			if (ss[a[i]][b[i]])return false;
		}

		rep(i, n) {
			bool exi = false;
			rep(j, n)if (ss[i][j])exi = true;
			if (exi)st.add_edge(i, i + n);
		}
		rep(i, c)if (typ[i] == 4) {
			rep(pre, n) {
				if (can[pre][a[i]] && can[pre][b[i]]) {
					st.add_edge(pre+n,pre);
				}
			}
		}
		st.scc();
		//cout << "nande " << c << "\n";
		if (!st.istwosat(n)) {
			return false;
		}
		return true;
	};
	int le = 0;
	int ri = m + 1;
	while (ri - le > 1) {
		int x = (le + ri) / 2;
		if (ok(x))le = x;
		else ri = x;
	}
	cout << le << "\n";
	
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//while(true)
	//expr();
	//int t; cin >> t; rep(i, t)
	while(cin>>n>>m,n)
	solve();
	return 0;
}
accuracy: 1
time_ms: 470
memory_kb: 30884
final_rank: 14

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

#define REP(i,n) for(int i=0; i<(int)(n); i++)
#define FOR(i,a,b) for(int i=(int)(a); i<(int)(b); i++)
#define FORR(i,a,b) for(int i=(int)(b)-1; i>=(int)(a); i--)

using ll = long long;
using pii = pair<int,int>;
using pid = pair<int,double>;

int n,m;
bool ok;
bool g[252][252];
int ty[12525], xi[12525], xj[12525];
vector<int> fook[252][252];

void f(int id){
  int s = xi[id], t = xj[id];
  if(ty[id] == 3){
    if(g[s][t] && g[t][s]){
      ok = false;
    }else if(g[s][s+n] && g[t][t+n]){
      ok = false;
    }
  }else if(ty[id] == 5){
    if(g[s][s+n] || g[t][t+n]){
      ok = false;
    }else if(g[s][t+n] && g[t][s+n]){
      ok = false;
    }
  }
}

void add_edge(int i, int j){
  if(g[i][j])return;
  g[i][j] = true;
  // (i,j) check
  for(int id : fook[i][j]){
    f(id);
  }
  // add others
  REP(s,2*n)if(g[s][i] && !g[s][j]){
    add_edge(s,j);
  }
  REP(t,2*n)if(g[j][t] && !g[i][t]){
    add_edge(i,t);
  }
  if(i+n==j){
    REP(s,n)if(g[s][i]){
      add_edge(i,s);
      add_edge(s,s+n);
      add_edge(s+n,i+n);
    }
  }
  if(i<n && j<n && g[j][j+n] && !g[j][i]){
    add_edge(i,i+n);
    add_edge(j,i);
    add_edge(i+n,j+n);
  }
}

int solve(){
  // initialize
  ok = true;
  REP(i,2*n)REP(j,2*n)g[i][j] = false;
  REP(i,2*n)REP(j,2*n)fook[i][j].clear();
  REP(i,m){
    int s = xi[i], t = xj[i];
    if(ty[i]==1){
      add_edge(s,t);
      add_edge(t+n,s+n);
    }else if(ty[i]==2){
      add_edge(s,t);
      add_edge(t+n,s+n);
      add_edge(t,s);
      add_edge(s+n,t+n);
    }else if(ty[i]==4){
      add_edge(s,t+n);
      add_edge(t,s+n);
    }else if(ty[i]==3){
      f(i);
      fook[s][s+n].push_back(i);
      fook[t][t+n].push_back(i);
      fook[s][t].push_back(i);
      fook[t][s].push_back(i);
    }else if(ty[i]==5){
      f(i);
      fook[s][s+n].push_back(i);
      fook[t][t+n].push_back(i);
      fook[s][t+n].push_back(i);
      fook[t][s+n].push_back(i);
    }
    if(!ok){
      return i;
    }
  }
  return m;
}

int naive(){
  int n2 = 1<<n;
  int ans = 0;
  REP(s,1<<n2){
    vector<int> ss(n);
    REP(i,n){
      REP(j,n2)if((j>>i&1) && (s>>j&1))ss[i] += 1<<j;
    }
    bool ok = true;
    REP(i,m){
      if(ty[i]==1){
        if((ss[xi[i]] & ss[xj[i]]) != ss[xi[i]])ok=false;
      }else if(ty[i]==2){
        if(ss[xi[i]] != ss[xj[i]])ok=false;
      }else if(ty[i]==3){
        if(ss[xi[i]] == ss[xj[i]])ok=false;
      }else if(ty[i]==4){
        if((ss[xi[i]] & ss[xj[i]]) != 0)ok=false;
      }else if(ty[i]==5){
        if((ss[xi[i]] & ss[xj[i]]) == 0)ok=false;
      }
      if(!ok){
        ans = max(ans, i);
        break;
      }
    }
    if(ok){
      ans = m;
      break;
    }
  }
  return ans;
}

int main(){
  while(false){
    n = 3;
    m = 8;
    REP(i,m){
      ty[i] = rand() % 5 + 1;
      xi[i] = rand() % n;
      xj[i] = rand() % (n-1);
      if(xj[i] >= xi[i])xj[i]++;
    }
    int ans1 = solve();
    int ans2 = naive();
    if(ans1 != ans2){
      printf("%d %d\n", n,m);
      REP(i,m)printf("%d %d %d\n",ty[i],xi[i]+1,xj[i]+1);
      printf("ans1: %d\n",ans1);
      printf("ans2: %d\n",ans2);
      return 0;
    }
  }
  while(true){
    scanf("%d%d",&n,&m);
    if(n+m==0)break;
    REP(i,m)scanf("%d%d%d",ty+i,xi+i,xj+i),xi[i]--,xj[i]--;
    printf("%d\n", solve());
  }
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 6572
final_rank: 11

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 105

enum Type{
	YES,
	NO,
	UNDEFINED,
};

enum Relation{
	IS_SUBSET_OF,
	EQUAL,
	DIFFERENT,
	NO_COMMON,
	HAVE_COMMON,
};

struct Info{
	Relation relation;
	int LEFT,RIGHT;
};

int N,M;
Info info[SIZE*SIZE];
Type is_Empty[SIZE],is_Subset[SIZE][SIZE],have_Common[SIZE][SIZE];
Relation relate_array[5] = {IS_SUBSET_OF,EQUAL,DIFFERENT,NO_COMMON,HAVE_COMMON};


bool func_Empty(int base){ //baseが新しく空集合であることが確定した

	//空集合の部分集合は、全て空集合でなければならない
	for(int i = 0; i < N; i++){
		if(is_Subset[i][base] == YES){
			if(is_Empty[i] == NO){

				return false;

			}else{

				is_Empty[i] = YES;
			}
		}
	}

	//空集合とHAVE_COMMONな要素があってはならない
	for(int i = 0; i < N; i++){
		if(i != base){
			if(have_Common[i][base] == YES){

				return false;

			}else{

				have_Common[i][base] = NO;
				have_Common[base][i] = NO;
			}
		}
	}

	return true;
}

bool check(int MID){

	//テーブルの初期化

	//空集合かどうか
	for(int i = 0; i < N; i++){

		is_Empty[i] = UNDEFINED;
	}

	//部分集合かどうか
	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(k == i){

				is_Subset[k][i] = YES;
			}
			else{

				is_Subset[k][i] = UNDEFINED;
			}
		}
	}

	//共通の要素があるかどうか
	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			have_Common[k][i] = UNDEFINED; //空集合なら、φ∩Φ = Φ
		}
	}

	//まずは、部分集合関係を演算する
	for(int i = 0; i <= MID; i++){
		if(info[i].relation == IS_SUBSET_OF){

			is_Subset[info[i].LEFT][info[i].RIGHT] = YES; //LEFTがRIGHTの部分集合

		}else if(info[i].relation == EQUAL){

			is_Subset[info[i].LEFT][info[i].RIGHT] = YES;
			is_Subset[info[i].RIGHT][info[i].LEFT] = YES;
		}
	}

	//ワーシャルフロイドで情報を伝達
	for(int mid = 0; mid < N; mid++){
		for(int start = 0; start < N; start++){
			if(is_Subset[start][mid] != YES)continue;
			for(int goal = 0; goal < N; goal++){
				if(is_Subset[mid][goal] != YES)continue;

				is_Subset[start][goal] = YES;
			}
		}
	}

	//共通要素を持つなら空集合ではない
	for(int i = 0; i <= MID; i++){
		if(info[i].relation == HAVE_COMMON){
			is_Empty[info[i].LEFT] = NO;
			is_Empty[info[i].RIGHT] = NO;

			have_Common[info[i].LEFT][info[i].RIGHT] = YES;
			have_Common[info[i].RIGHT][info[i].LEFT] = YES;

			//LEFT∩RIGHT != Φなので、[LEFTおよびLEFTとおなじもの]は[RIGHTおよびRIGHTと同じもの]とHAVE_COMMONになる
			for(int a = 0; a < N; a++){
				if(is_Subset[a][info[i].LEFT] == YES && is_Subset[info[i].LEFT][a] == YES){
					for(int b = 0; b < N; b++){
						if(is_Subset[b][info[i].RIGHT] == YES && is_Subset[info[i].RIGHT][b] == YES){

							is_Empty[a] = NO;
							is_Empty[b] = NO;

							have_Common[a][b] = YES;
							have_Common[b][a] = YES;
						}
					}
				}
			}
		}
	}

	//LEFT∩RIGHT = Φの場合を処理
	for(int i = 0; i <= MID; i++){
		if(info[i].relation == NO_COMMON){

			//LEFT∩RIGHT = Φより、A⊆LEFT,A⊆RIGHTとなるAについて、A = Φが成り立つ
			for(int k = 0; k < N; k++){
				if(is_Subset[k][info[i].LEFT] == YES && is_Subset[k][info[i].RIGHT] == YES){

					if(is_Empty[k] == NO){
						return false;
					}else{

						is_Empty[k] = YES;
						if(!func_Empty(k)){ //情報の反映
							return false;
						}
					}
				}
			}

			//矛盾
			if(have_Common[info[i].LEFT][info[i].RIGHT] == YES){

				return false;

			}else{

				have_Common[info[i].LEFT][info[i].RIGHT] = NO;
			}

			//LEFT⊆RIGHTでNO_COMMONなら、少なくともLEFTは空集合
			if(is_Subset[info[i].LEFT][info[i].RIGHT] == YES){

				if(is_Empty[info[i].LEFT] == NO){

					return false;

				}else{

					is_Empty[info[i].LEFT] = YES;
					if(!func_Empty(info[i].LEFT)){
						return false;
					}

				}
			}

			//RIGHT⊆LEFTでNO_COMMONなら、少なくともRIGHTは空集合
			if(is_Subset[info[i].RIGHT][info[i].LEFT] == YES){
				if(is_Empty[info[i].RIGHT] == NO){

					return false;

				}else{

					is_Empty[info[i].RIGHT] = YES;
					if(!func_Empty(info[i].RIGHT)){
						return false;
					}
				}
			}
		}
	}


	//DIFFERENTを確認
	for(int i = 0; i <= MID; i++){
		if(info[i].relation != DIFFERENT)continue;

		if(is_Subset[info[i].LEFT][info[i].RIGHT] == YES &&
				is_Subset[info[i].RIGHT][info[i].LEFT] == YES){

			return false;

		}else if(is_Empty[info[i].LEFT] == YES && is_Empty[info[i].RIGHT] == YES){ //両方が空集合なら不可

			return false;
		}
	}

	//emptyをもう一度確認
	for(int i = 0; i < N; i++){
		if(is_Empty[i] != YES)continue;

		//空集合の部分集合は、全て空集合でなければならない
		for(int k = 0; k < N; k++){
			if(is_Subset[k][i] == YES){
				if(is_Empty[k] == NO){

					return false;

				}else{

					is_Empty[k] = YES;
				}
			}
		}

		//空集合とHAVE_COMMONな要素があってはならない
		for(int k = 0; k < N; k++){
			if(k != i){
				if(have_Common[k][i] == YES){

					return false;

				}else{

					have_Common[k][i] = NO;
					have_Common[i][k] = NO;
				}
			}
		}
	}

	//have_Commonの情報を更新
	for(int a = 0; a < N; a++){
		for(int b = 0; b < N; b++){
			if(have_Common[a][b] != NO)continue;
			for(int c = 0; c < N; c++){
				if(is_Subset[c][a] != YES)continue;
				for(int d = 0; d < N; d++){
					if(is_Subset[d][b] != YES)continue;

					if(have_Common[c][d] == YES){
						return false;
					}else{
						have_Common[c][d] = NO;
						have_Common[d][c] = NO;
					}
				}
			}
		}
	}

	//HAVE_COMMONを最後に確認
	for(int i = 0; i <= MID; i++){
		if(info[i].relation != HAVE_COMMON)continue;

		if(have_Common[info[i].LEFT][info[i].RIGHT] == NO){

			return false;

		}else if(is_Empty[info[i].LEFT] == YES || is_Empty[info[i].RIGHT] == YES){

			return false;
		}
	}

	return true;
}

void func(){

	int command;

	for(int i = 0; i < M; i++){

		scanf("%d %d %d",&command,&info[i].LEFT,&info[i].RIGHT);

		command--;

		info[i].LEFT--;
		info[i].RIGHT--;
		info[i].relation = relate_array[command];
	}

	//2分探索で、条件を満たす最大行数を求める
	int ans = -1;
	int L = 0,R = M-1,MID = (L+R)/2;

	while(L <= R){

		if(check(MID)){

			ans = MID;
			L = MID+1;

		}else{

			R = MID-1;
		}
		MID = (L+R)/2;
	}

	printf("%d\n",ans+1);
}

int main(){

	while(true){

		scanf("%d %d",&N,&M);
		if(N == 0 && M == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 4730
memory_kb: 3424
final_rank: 13

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define all(c) c.begin(),c.end()
#define pb push_back
#define fs first
#define sc second
#define show(x) cout << #x << " = " << x << endl
#define chmin(x,y) x=min(x,y)
#define chmax(x,y) x=max(x,y)
using namespace std;
int N,M,t[10000],v[10000],u[10000];
bool can(int M){
	bool e[100][100]={},emp[10000]={},no[100][100]={};
	rep(i,N) e[i][i]=1;
	rep(i,M){
		if(t[i]==1) e[u[i]][v[i]]=1;
		if(t[i]==2) e[u[i]][v[i]]=e[v[i]][u[i]]=1;
	}
	rep(i,N) rep(j,N) rep(k,N) e[j][k]|=(e[j][i]&&e[i][k]);
	rep(i,M){
		if(t[i]==4){
			int a=v[i],b=u[i];
			rep(c,N) if(e[a][c]&&e[b][c]) emp[c]=1;
			no[a][b]=no[b][a]=1;
		}
	}
	rep(i,N) if(emp[i]){
		rep(j,N) if(e[i][j]) emp[j]=1;
	}
	rep(i,N) rep(j,N) if(no[i][j]){
		rep(I,N) rep(J,N){
			if(e[i][I]&&e[j][J]){
				no[I][J]=1;
			}
		}
	}
	// puts("no");
	// rep(i,N){
	// 	rep(j,N) cout<<no[i][j]<<" ";
	// 	puts("");
	// }
	rep(i,M){
		int a=v[i],b=u[i];
		if(t[i]==3){
			if(emp[a]&&emp[b]) return 0;
			if(e[a][b]&&e[b][a]) return 0;
		}
		if(t[i]==5){
			if(emp[a]||emp[b]) return 0;
			if(no[a][b]) return 0;
		}
	}
	return 1;
}
int main(){
	while(true){
		cin>>N>>M;
		if(N==0) break;
		rep(i,M){
			cin>>t[i]>>v[i]>>u[i],v[i]--,u[i]--;
		}
		int ub=M+1,lb=0;
		while(ub-lb>1){
			int m=(ub+lb)/2;
			if(can(m)) lb=m;
			else ub=m;
		}
		cout<<lb<<endl;
	}
}
accuracy: 1
time_ms: 3740
memory_kb: 3160
final_rank: 12

code_snippet: #include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>

#define msn(x) (memset((x),0,sizeof((x))))
#define msi(x) (memset((x),-1,sizeof((x))))
#define msx(x) (memset((x),0x7f,sizeof((x))))
#define fuck(x) cerr << #x << " <- " << x << endl
#define acer cout<<"sb"<<endl
typedef long long ll;
using namespace std;
const int maxn=107;
const int maxm=1e4+7;
struct node
{
    int o,u,v;
}q[maxm];
vector<node>cmp;
int n,m;
bool dp[maxn][maxn];
bool emp[maxn][maxn];
vector<int>a,b;
bool check(int x)
{
    //queue< pair<int ,int> >q;
    cmp.clear();
    msn(dp);
    msn(emp);
    for(int i=1;i<=n;i++)dp[i][i]=1;
    for(int i=0;i<x;i++)
    {
        node &now=q[i];
        if(now.o==1)
        {
            dp[now.u][now.v]=1;
        }
        else if(now.o==2)
        {
            dp[now.u][now.v]=dp[now.v][now.u]=1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            for(int k=1;k<=n;k++)
                dp[j][k]|=(dp[j][i]&&dp[i][k]);
        }
    }

    for(int i=0;i<x;i++)
    {
         node &now=q[i];
        if(now.o==4)cmp.push_back(now);
    }
   // random_shuffle(cmp.begin(),cmp.end());
    for(int z=0;z<cmp.size();z++)
    {
         node &now=cmp[z];
        if(emp[now.u][now.v])continue;
            a.clear(),b.clear();
            for(int i=1;i<=n;i++)if(dp[i][now.u])a.push_back(i);
            for(int i=1;i<=n;i++)if(dp[i][now.v])b.push_back(i);
             for(int i=0;i<a.size();i++)
            {
                for(int j=0;j<b.size();j++)
                emp[b[j]][a[i]]=emp[a[i]][b[j]]=1;
            }
    }
    for(int i=0;i<x;i++)
    {
         node &now=q[i];
        if(now.o==5)
        {
            if(emp[now.u][now.v]||emp[now.u][now.u]||emp[now.v][now.v])return 0;
        }
    }
    for(int i=0;i<x;i++)
    {
         node &now=q[i];
         if(now.o==3)
         {
             if(emp[now.u][now.u]==1&&emp[now.v][now.v]==1)return 0;
             if(dp[now.u][now.v]==1&&dp[now.v][now.u]==1)return 0;
         }
    }
    return 1;
}
int main()
{
    while(scanf("%d %d",&n,&m))
    {
        if(n==0&&m==0)break;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&q[i].o,&q[i].u,&q[i].v);
        }
    int l=0,r=m;
        while(l<r)
        {
            int mid=(l+r)/2+1;
            if(check(mid))l=mid;
            else r=mid-1;
        }
       printf("%d\n",l);
    }
    return 0;
}
accuracy: 1
time_ms: 290
memory_kb: 1556
final_rank: 6

code_snippet: #include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>

#define msn(x) (memset((x),0,sizeof((x))))
#define msi(x) (memset((x),-1,sizeof((x))))
#define msx(x) (memset((x),0x7f,sizeof((x))))
#define fuck(x) cerr << #x << " <- " << x << endl
#define acer cout<<"sb"<<endl
typedef long long ll;
using namespace std;
const int maxn=107;
const int maxm=1e4+7;
struct node
{
    int o,u,v;
}q[maxm];
vector<node>cmp;
int n,m;
bool dp[maxn][maxn];
bool emp[maxn][maxn];
vector<int>a,b;
bool check(int x)
{
    //queue< pair<int ,int> >q;
    cmp.clear();
    msn(dp);
    msn(emp);
    for(int i=1;i<=n;i++)dp[i][i]=1;
    for(int i=0;i<x;i++)
    {
        node &now=q[i];
        if(now.o==1)
        {
            dp[now.u][now.v]=1;
        }
        else if(now.o==2)
        {
            dp[now.u][now.v]=dp[now.v][now.u]=1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            for(int k=1;k<=n;k++)
                dp[j][k]|=(dp[j][i]&&dp[i][k]);
        }
    }

    for(int i=0;i<x;i++)
    {
         node &now=q[i];
        if(now.o==4)cmp.push_back(now);
    }
    random_shuffle(cmp.begin(),cmp.end());
    for(int z=0;z<cmp.size();z++)
    {
         node &now=cmp[z];
        if(emp[now.u][now.v])continue;
            a.clear(),b.clear();
            for(int i=1;i<=n;i++)if(dp[i][now.u])a.push_back(i);
            for(int i=1;i<=n;i++)if(dp[i][now.v])b.push_back(i);
             for(int i=0;i<a.size();i++)
            {
                for(int j=0;j<b.size();j++)
                emp[b[j]][a[i]]=emp[a[i]][b[j]]=1;
            }
    }
    for(int i=0;i<x;i++)
    {
         node &now=q[i];
        if(now.o==5)
        {
            if(emp[now.u][now.v]||emp[now.u][now.u]||emp[now.v][now.v])return 0;
        }
    }
    for(int i=0;i<x;i++)
    {
         node &now=q[i];
         if(now.o==3)
         {
             if(emp[now.u][now.u]==1&&emp[now.v][now.v]==1)return 0;
             if(dp[now.u][now.v]==1&&dp[now.v][now.u]==1)return 0;
         }
    }
    return 1;
}
int main()
{
    while(scanf("%d %d",&n,&m))
    {
        if(n==0&&m==0)break;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&q[i].o,&q[i].u,&q[i].v);
        }
    int l=0,r=m;
        while(l<r)
        {
            int mid=(l+r)/2+1;
            if(check(mid))l=mid;
            else r=mid-1;
        }
       printf("%d\n",l);
    }
    return 0;
}
accuracy: 1
time_ms: 290
memory_kb: 1556
final_rank: 6

code_snippet: #include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>

using namespace std;

int M;
int type[10100],is[10100],js[10100];

vector<int> G[200];
bool reached[200];
int N;

void init_graph(){
	for(int i=0;i<N*2;i++) G[i].clear();
}

void add_edge(int t,int i,int j){
	if(t==1){
		G[i].push_back(j);
		G[j+N].push_back(i+N);
	}else if(t==2){
		add_edge(1,i,j);
		add_edge(1,j,i);
	}else if(t==4){
		G[i].push_back(j+N);
		G[j].push_back(i+N);
	}
}

bool bfs(int s1,int s2){
	for(int i=0;i<N*2;i++) reached[i]=false;
	reached[s1]=true;
	reached[s2]=true;
	queue<int> que;
	que.push(s1);
	que.push(s2);
	while(!que.empty()){
		int v=que.front();
		que.pop();
		for(int i=0;i<G[v].size();i++){
			int u=G[v][i];
			if(reached[u]) continue;
			reached[u]=true;
			if(u>=N){
				if(reached[u-N]) return false;
			}else{
				if(reached[u+N]) return false;
			}
			que.push(u);
		}
	}
	return true;
}

bool check(int K){
	init_graph();
	for(int i=0;i<K;i++) add_edge(type[i],is[i],js[i]);
	bool ok=true;
	for(int i=0;i<K;i++){
		if(type[i]==3){
			int u=is[i],v=js[i]+N;
			bool flg=bfs(u,v);
			u+=N;
			v-=N;
			bool flg2=bfs(u,v);
			if(flg==false&&flg2==false){
				return false;
			}
		}else if(type[i]==5){
			int u=is[i],v=js[i];
			bool flg=bfs(u,v);
			if(!flg) return false;
		}
	}
	return true;
}

int main(){
	while(true){
		scanf("%d%d",&N,&M);
		if(N==0&&M==0) break;
		for(int i=0;i<M;i++){
			scanf("%d%d%d",type+i,is+i,js+i);
			is[i]--;js[i]--;
		}
		int lb=1,ub=M+1;
		while(ub-lb>1){
			int mid=(ub+lb)/2;
			bool flg=check(mid);
			if(flg) lb=mid;
			else ub=mid;
		}
		printf("%d\n",lb);
	}
	return 0;
}
accuracy: 1
time_ms: 270
memory_kb: 1532
final_rank: 4

code_snippet: #include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cctype>
using namespace std;
#define N 105
int n , m;
struct query
{
    int id , x , y;
}q[N * N];
bool g[N][N] , f[N][N];
bool Q(int x , int y)
{
    for (int i = 1 ; i <= n ; ++ i)
        if (g[x][i] && f[y][i] || g[y][i] && f[x][i])
            return 1;
    return 0;
}
bool check(int V)
{
    int i , j , k, x , y;
    memset(f , 0 , sizeof(f));
    memset(g , 0 , sizeof(g));
    for (i = 1 ; i <= n ; ++ i)
        g[i][i] = 1;
    for (i = 1 ; i <= V ; ++ i)
        if (q[i].id <= 2)
        {
            x = q[i].x , y = q[i].y;
            g[x][y] = 1;
            if (q[i].id == 2)
                g[y][x] = 1;
        }
    for (k = 1 ; k <= n ; ++ k)
        for (i = 1 ; i <= n ; ++ i) if (g[i][k])
            for (j = 1 ; j <= n ; ++ j) if (g[k][j])
                g[i][j] = 1;
    for (i = 1 ; i <= V ; ++ i)
        if (q[i].id == 4)
        {
            x = q[i].x , y = q[i].y;
           /* for (j = 1 ; j <= n ; ++ j) if (g[j][x])
                for (k = 1 ; k <= n ; ++ k) if (g[k][y])
                    f[j][k] = f[k][j] = 1;*/
            for (j = 1 ; j <= n ; ++ j) if (g[j][x])
                f[j][y] = 1;
            for (j = 1 ; j <= n ; ++ j) if (g[j][y])
                f[j][x] = 1;
        }
    for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) f[i][j] |= f[j][i];
    for (i = 1 ; i <= V ; ++ i)
    {
        x = q[i].x , y = q[i].y;
        if (q[i].id == 3) // x != y
        {//      x , y = empty           x == y
            if (g[x][y] && g[y][x])
                return 0;
            if (Q(x , x) && Q(y , y))
                return 0;
        }
        else if (q[i].id == 5) // x ins y != empty
        {    //x = empty   y = empty   x ins y == empty
            if (Q(x , x) || Q(y , y) || Q(x , y) || Q(y , x))
                return 0;
        }
    }
    return 1;
}

int main()
{
    while (scanf("%d%d",&n,&m))
    {
    	if(n == 0 && m == 0) break;
        for (int i = 1 ; i <= m ; ++ i)
           scanf("%d%d%d",&q[i].id, &q[i].x , &q[i].y);

        int top = 1 , bot = m , mid;
        while (top < bot)
        {
            mid = top + bot + 1 >> 1;
            if (check(mid))
                top = mid;
            else
                bot = mid - 1;
        }
        printf("%d\n" , top);
    }
    return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 1156
final_rank: 3

code_snippet: #include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>

using namespace std;

const int MAXN = 1e4+10;
const int MAXG = 110;

int n,m;
int x[MAXN],op[MAXN],y[MAXN];
int f[MAXG][MAXG],g[MAXG][MAXG];
bool vis[MAXG] ;

void dfs(int u){
    int i, k;
    vis[u] = 1;
    for(i=1;i<=n;i++)
    if(g[u][i]){
        if(!vis[i]) dfs(i);
        for(k=1;k<=n;k++)
        if(f[i][k])
        f[u][k] = f[k][u] = 1;
    }
}

bool check(int mid) {
    for (int i=1; i<=n; i++)
        for (int j=1; j<=n; j++)
            f[i][j] = 0 ;
    for (int i=1; i<=n; i++) {
        for (int j=1; j<=n; j++) g[i][j]=0;
        g[i][i]=1;
    }
    for (int Q=1; Q<=mid; Q++) {
        int i = x[Q] , j = y[Q] , ope = op[Q];
        if (ope==1) g[i][j] = 1 ;
        else if (ope==2) g[i][j] = g[j][i] = 1 ;
        else if (ope==4) f[i][j] = f[j][i] = 1 ;
    }
    for (int k = 1 ; k <= n ; k++)
        for (int i = 1 ; i <= n ; i++)
            for (int j = 1 ; j <= n ; j++)
                if (g[i][k] && g[k][j]) g[i][j] = 1 ;

    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
    if(!vis[i]) dfs(i);

    for (int Q = 1 ; Q <= mid ; Q++) {
        int i = x[Q] , j = y[Q] , ope = op[Q];
        if (ope==3) {
            if (f[i][i] && f[j][j]) return false ;
            if (g[i][j] && g[j][i]) return false ;
        } else if (ope==5) {
            if (f[i][j] || f[j][i] || f[i][i] || f[j][j]) return false ;
        }
    }
    return true ;
}

int main() {
    while (~scanf("%d%d",&n,&m) && (n+m)) {
        for (int i=1; i<=m; i++) scanf("%d%d%d",&op[i],&x[i],&y[i]);
        int l=1,r=m,ans=0;
        while (l<=r) {
            int mid=l+r>>1;
            if (check(mid)) {
                ans=mid;
                l=mid+1;
            } else r=mid-1;
        }
        printf("%d\n",ans);
    }
    return 0;
}
accuracy: 1
time_ms: 310
memory_kb: 1400
final_rank: 5

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <bitset>

#define frs first
#define scn second
#define mkp make_pair
#define phb push_back
#define ppb pop_back

using namespace std;

typedef pair< int, int > Pr;
typedef pair< int, Pr > Cmd;

int N, M;
Cmd C[10010];

vector< int > graph[110], stk;
int dfi, dfn[110], lwn[110], cmp[110];
int vst[110], vst_cnt;
bool is_in_stk[110];

bitset< 110 > dscn[110], ancs[110];
bool is_zero[110], is_nonzero[110];
bitset< 110 > is_intr[110];

void read();
void soups_on();
bool yee_haw(int);
void tarjan(int);
void dfs(int, int);

int main() {
  ios::sync_with_stdio(false);
  while (cin >> N >> M, N + M)
    read(), soups_on();

  return 0;
}

void read() {
  int s, u, v;

  for (int i = 0; i < M; ++i)
    cin >> s >> u >> v, C[i] = mkp(s, mkp(u, v));
}

void soups_on() {
  int low, up, mid;

  low = 0, up = M;
  while (low < up) {
    mid = (low + up) / 2 + 1;
    if (yee_haw(mid))
      low = mid;
    else
      up = mid - 1;
  }

  cout << low << "\n";
}

bool yee_haw(int lm) {
  int u, v;
  vector< Pr > t[6];

  for (int i = 0; i < lm; ++i)
    t[C[i].frs].phb(C[i].scn);

  for (int i = 1; i <= N; ++i)
    graph[i].clear();

  // build graph
  for (int i = 0; i < int(t[1].size()); ++i) {
    u = t[1][i].frs, v = t[1][i].scn;
    graph[v].phb(u);
  }

  for (int i = 0; i < int(t[2].size()); ++i) {
    u = t[2][i].frs, v = t[2][i].scn;
    graph[u].phb(v), graph[v].phb(u);
  }

  // find scc
  ++vst_cnt, dfi = 0;
  for (int i = 1; i <= N; ++i)
    if (vst[i] != vst_cnt)
      tarjan(i);

  for (int i = 1; i <= N; ++i)
    dscn[i].reset(), ancs[i].reset(), dscn[i].set(i), ancs[i].set(i);

  // find descendants and ancestors
  for (int i = 1; i <= N; ++i)
    if (cmp[i] == i)
      ++vst_cnt, dfs(i, i);

  fill(&is_zero[0], &is_zero[N + 1], false);
  fill(&is_nonzero[0], &is_nonzero[N + 1], false);

  for (int i = 1; i <= N; ++i)
    is_intr[i].reset();

  // dealing with constraint type 5

  for (int i = 0; i < int(t[5].size()); ++i) {
    u = cmp[t[5][i].frs], v = cmp[t[5][i].scn];
    bitset< 110 > tmp = ancs[u] | ancs[v];
    for (int j = 1; j <= N; ++j)
      if (ancs[u][j] || ancs[v][j])
        is_nonzero[j] = true, is_intr[j] |= tmp;
  }

  // dealing with constraint type 4
  for (int i = 0; i < int(t[4].size()); ++i) {
    u = cmp[t[4][i].frs], v = cmp[t[4][i].scn];
    if (u == v)
      is_zero[u] = true;
    else {
      if (is_intr[u][v])
        return false;
      bitset< 110 > tmp = dscn[u] & dscn[v];
      for (int j = 1; j <= N; ++j)
        if (tmp[j])
          is_zero[j] = true;
    }
  }

  // dealing with constraint type 3
  for (int i = 0; i < int(t[3].size()); ++i) {
    u = cmp[t[3][i].frs], v = cmp[t[3][i].scn];
    if (u == v) return false;
    if (is_zero[u] && is_zero[v]) return false;
  }

  // dealing with other confliction between constraint type 4 and 5
  for (int i = 1; i <= N; ++i)
    if (cmp[i] == i && (is_zero[i] && is_nonzero[i]))
      return false;

  return true;
}

void tarjan(int u) {
  int v;

  vst[u] = vst_cnt;
  dfn[u] = lwn[u] = ++dfi;
  stk.phb(u), is_in_stk[u] = true;

  for (int i = 0; i < int(graph[u].size()); ++i)
    if (vst[v = graph[u][i]] != vst_cnt)
      tarjan(v), lwn[u] = min(lwn[u], lwn[v]);
    else if (is_in_stk[v])
      lwn[u] = min(lwn[u], dfn[v]);

  if (dfn[u] == lwn[u]) {
    do {
      v = stk.back(), stk.ppb(), is_in_stk[v] = false;
      cmp[v] = u;
    } while (u != v);
  }
}

void dfs(int u, int k) {
  int v;

  vst[u] = vst_cnt;
  for (int i = 0; i < int(graph[u].size()); ++i)
    if (vst[v = graph[u][i]] != vst_cnt) {
      if (cmp[v] == v)
        dscn[k].set(v), ancs[v].set(k);
      dfs(v, k);
    }
}
accuracy: 1
time_ms: 70
memory_kb: 1660
final_rank: 1

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <bitset>

#define frs first
#define scn second
#define mkp make_pair
#define phb push_back
#define ppb pop_back

using namespace std;

typedef pair< int, int > Pr;
typedef pair< int, Pr > Cmd;

int N, M;
Cmd C[10010];

vector< int > graph[110], stk;
int dfi, dfn[110], lwn[110], cmp[110];
int vst[110], vst_cnt;
bool is_in_stk[110];

bitset< 110 > dscn[110], ancs[110];
bool is_zero[110], is_nonzero[110];
bitset< 110 > is_intr[110];

void read();
void soups_on();
bool yee_haw(int);
void tarjan(int);
void dfs(int, int);

int main() {
  while (cin >> N >> M, N + M)
    read(), soups_on();

  return 0;
}

void read() {
  int s, u, v;

  for (int i = 0; i < M; ++i)
    cin >> s >> u >> v, C[i] = mkp(s, mkp(u, v));
}

void soups_on() {
  int low, up, mid;

  low = 0, up = M;
  while (low < up) {
    mid = (low + up) / 2 + 1;
    if (yee_haw(mid))
      low = mid;
    else
      up = mid - 1;
  }

  cout << low << "\n";
}

bool yee_haw(int lm) {
  int u, v;
  vector< Pr > t[6];

  for (int i = 0; i < lm; ++i)
    t[C[i].frs].phb(C[i].scn);

  for (int i = 1; i <= N; ++i)
    graph[i].clear();

  // build graph
  for (int i = 0; i < int(t[1].size()); ++i) {
    u = t[1][i].frs, v = t[1][i].scn;
    graph[v].phb(u);
  }

  for (int i = 0; i < int(t[2].size()); ++i) {
    u = t[2][i].frs, v = t[2][i].scn;
    graph[u].phb(v), graph[v].phb(u);
  }

  // find scc
  ++vst_cnt, dfi = 0;
  for (int i = 1; i <= N; ++i)
    if (vst[i] != vst_cnt)
      tarjan(i);

  for (int i = 1; i <= N; ++i)
    dscn[i].reset(), ancs[i].reset(), dscn[i].set(i), ancs[i].set(i);

  // find descendants and ancestors
  for (int i = 1; i <= N; ++i)
    if (cmp[i] == i)
      ++vst_cnt, dfs(i, i);

  fill(&is_zero[0], &is_zero[N + 1], false);
  fill(&is_nonzero[0], &is_nonzero[N + 1], false);

  for (int i = 1; i <= N; ++i)
    is_intr[i].reset();

  // dealing with constraint type 5

  for (int i = 0; i < int(t[5].size()); ++i) {
    u = cmp[t[5][i].frs], v = cmp[t[5][i].scn];
    bitset< 110 > tmp = ancs[u] | ancs[v];
    for (int j = 1; j <= N; ++j)
      if (ancs[u][j] || ancs[v][j])
        is_nonzero[j] = true, is_intr[j] |= tmp;
  }

  // dealing with constraint type 4
  for (int i = 0; i < int(t[4].size()); ++i) {
    u = cmp[t[4][i].frs], v = cmp[t[4][i].scn];
    if (u == v)
      is_zero[u] = true;
    else {
      if (is_intr[u][v])
        return false;
      bitset< 110 > tmp = dscn[u] & dscn[v];
      for (int j = 1; j <= N; ++j)
        if (tmp[j])
          is_zero[j] = true;
    }
  }

  // dealing with constraint type 3
  for (int i = 0; i < int(t[3].size()); ++i) {
    u = cmp[t[3][i].frs], v = cmp[t[3][i].scn];
    if (u == v) return false;
    if (is_zero[u] && is_zero[v]) return false;
  }

  // dealing with other confliction between constraint type 4 and 5
  for (int i = 1; i <= N; ++i)
    if (cmp[i] == i && (is_zero[i] && is_nonzero[i]))
      return false;

  return true;
}

void tarjan(int u) {
  int v;

  vst[u] = vst_cnt;
  dfn[u] = lwn[u] = ++dfi;
  stk.phb(u), is_in_stk[u] = true;

  for (int i = 0; i < int(graph[u].size()); ++i)
    if (vst[v = graph[u][i]] != vst_cnt)
      tarjan(v), lwn[u] = min(lwn[u], lwn[v]);
    else if (is_in_stk[v])
      lwn[u] = min(lwn[u], dfn[v]);

  if (dfn[u] == lwn[u]) {
    do {
      v = stk.back(), stk.ppb(), is_in_stk[v] = false;
      cmp[v] = u;
    } while (u != v);
  }
}

void dfs(int u, int k) {
  int v;

  vst[u] = vst_cnt;
  for (int i = 0; i < int(graph[u].size()); ++i)
    if (vst[v = graph[u][i]] != vst_cnt) {
      if (cmp[v] == v)
        dscn[k].set(v), ancs[v].set(k);
      dfs(v, k);
    }
}
accuracy: 1
time_ms: 110
memory_kb: 1648
final_rank: 2