要求输出可能达到的最大值,显然二分
x数组只能为0或1,可以联想到twosat
只有当 x[a[dep]] + x[b[dep]] != c[dep]时候才能进入下一层 则可以根据这个条件加限制
c == 0时 a b 不能同时为0
c == 1时 a b 必须相等
c == 2时 a b 不能同时为1
//#pragma warning (disable: 4786)
//#pragma comment (linker, "/STACK:16777216")
//HEAD
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
//LOOP
#define FF(i, a, b) for(int i = (a); i < (b); ++i)
#define FD(i, b, a) for(int i = (b) - 1; i >= (a); --i)
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FED(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
#define CPY(a, b) memcpy(a, b, sizeof(a))
#define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
//STL
#define SZ(V) (int)V.size()
#define PB push_back
#define EQ(a, b) (fabs((a) - (b)) <= 1e-10)
#define ALL(c) (c).begin(), (c).end()
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p)
#define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q)
#define RS(s) scanf("%s", s)
//OUTPUT
#define WI(n) printf("%d\n", n)
#define WS(s) printf("%s\n", s)
typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> VI;
const int INF = 100000000;
const double eps = 1e-10;
const int maxn = 250;
int n, m;
int a[10100], b[10100], c[10100];
struct TwoSAT{
int n;
vector<int> G[maxn * 2];
bool mark[maxn * 2];
int S[maxn * 2], c;
bool dfs(int x)
{
if (mark[x ^ 1])
return false;
if (mark[x])
return true;
mark[x] = true;
S[c++] = x;
for (int i = 0; i < G[x].size(); i++)
if (!dfs(G[x][i]))
return false;
return true;
}
void init(int n)
{
this->n = n;
for (int i = 0; i < n * 2; i++)
G[i].clear();
memset(mark, 0, sizeof(mark));
}
void add_clause(int x, int xval, int y, int yval)
{
x = x * 2 + xval;
y = y * 2 + yval;
G[x ^ 1].push_back(y);
G[y ^ 1].push_back(x);
}
bool solve()
{
for (int i = 0; i < n * 2; i += 2)
if (!mark[i] && !mark[i + 1])
{
c = 0;
if (!dfs(i))
{
while (c > 0)
mark[S[--c]] = false;
if (!dfs(i + 1))
return false;
}
}
return true;
}
};
TwoSAT sat;
bool test(int x)
{
sat.init(n);
REP(i, x)
{
if (c[i] == 0)
sat.add_clause(a[i], 1, b[i], 1);
else if (c[i] == 1)
{
// if (a[i] != b[i])
// {
sat.add_clause(a[i], 1, b[i], 0);
sat.add_clause(a[i], 0, b[i], 1);
// }
}
else if (c[i] == 2)
sat.add_clause(a[i], 0, b[i], 0);
}
return sat.solve();
}
void solve()
{
int L = 0, R = m;
while (L <= R)
{
int mid = (L + R) >> 1;
if (test(mid)) L = mid + 1;
else R = mid - 1;
}
// test(R);
// for (int i = 0; i < 2 * n; i += 2)
// {
// if (sat.mark[i])
// cout << 0 << ' ';
// else
// cout << 1 << ' ';
// }
// cout << endl;
printf("%d\n", R);
}
int main()
{
int T;
RI(T);
while (T--)
{
RII(n, m);
REP(i, m)
RIII(a[i], b[i], c[i]);
solve();
}
}