2 - sat建图:x[a[i]] = 1, x[a[i] + n] = 0
c[i] == 0
a[i] + n --> b[i]
b[i] + n --> a[i]
c[i] == 1
a[i] + n --> b[i] + n
b[i] + n --> a[i] + n
a[i] ---> b[i]
b[i] ---> a[i]
c[i]==2
a[i] ----> b[i] + n
b[i] ----> a[i] + n
二分
/*
author : csuchenan
prog : hdu3715
algorithm : 2-sat
*/
#include <cstdio>
#include <cstring>
#include <vector>
using std::vector;
const int maxn = 10000;
int a[maxn+5];
int c[maxn+5];
int b[maxn+5];
int dfn[200*2+5];
int low[200*2+5];
int col[200*2+5];
int stack[200*2+5];
bool ins[200*2+5];
vector<int> G[200*2+5];
int top, depth, color;
int n, m;
void add_edge(int x, int y){
G[x].push_back(y);
}
int min(int x, int y){
if(x < y)
return x;
return y;
}
void tarjan(int v){
dfn[v] = low[v] = ++ depth;
ins[v] = true;
stack[++ top] = v;
for(int i = 0; i != G[v].size(); i++){
int u = G[v][i];
if(dfn[u]==0){
tarjan(u);
low[v] = min(low[v], low[u]);
}
else if(ins[u]){
low[v] = min(low[v], dfn[u]);
}
}
if(dfn[v] == low[v]){
int k;
color ++;
do{
k = stack[top--];
ins[k] = false ;
col[k] = color ;
}while(k != v);
}
}
bool check(int t){
memset(dfn, 0, sizeof(dfn));
memset(ins, 0, sizeof(ins));
memset(col, 0, sizeof(col));
for(int i = 0; i < 2*n+2; i ++){
G[i].clear();
}
//build
for(int i = 0 ; i < t; i ++){
if(c[i]==0){
add_edge(a[i]+n, b[i]);
add_edge(b[i]+n, a[i]);
}
else if(c[i]==1){
add_edge(a[i]+n, b[i]+n);
add_edge(b[i]+n, a[i]+n);
add_edge(a[i], b[i]);
add_edge(b[i], a[i]);
}
else{
add_edge(a[i], b[i]+n);
add_edge(b[i], a[i]+n);
}
}
top = 0;
color = 0;
depth = 0;
for(int i = 0; i < n + n; i ++){
if(dfn[i]==0)
tarjan(i);
}
for(int i = 0 ; i < n; i ++){
if(col[i]==col[i+n]){
return false;
}
}
return true;
}
int main(){
int T;
// freopen("test.in", "r", stdin);
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
for(int i = 0; i < m; i ++){
scanf("%d%d%d", &a[i], &b[i], &c[i]);
}
int l = 0, r= m;
while(l <= r){
int mid = (l+r)>>1;
if(check(mid)){
l = mid + 1;
}
else r = mid - 1;
}
printf("%d\n", r);
}
return 0;
}