先二分图染色,求出标号为1的边的联通块个数。然后分两种况讨论,1是联通块内的情况,2是联通块之间的情况。
第一种情况很简单,可以直接判断该联通块是选0这种颜色还是1这种颜色。第二种情况用two-sat就好了。
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define pb push_back
using namespace std;
const int MX = 4e5+7;
vector<int> G1[MX],G0[MX];
int col[MX],blo[MX],cb[MX];
bool dfs(int u, int fa, int c, int cnt)
{
col[u] = c;
blo[u] = cnt;
for(int v : G1[u]){
if(col[v] == -1){
bool flag = dfs(v,u,c^1,cnt);
if(!flag) return 0;
}
else if(col[v] != c^1) return 0;
}
return 1;
}
struct TwoSAT{
int n;
vector<int> G[MX*2];
bool mark[MX*2],vis[MX*2];
int s[MX*2], c;
bool dfs(int x){
if(mark[x^1] || vis[x^1]) return 0;
if(mark[x]) return 1;
mark[x] = 1;
s[c++] = x;
for(int i = 0; i < G[x].size(); i++)
if(!dfs(G[x][i])) return 0;
return 1;
}
void init(int n){
this->n = n;
for(int i = 0; i < n*2; i++) G[i].clear(), mark[i] = vis[i] = 0;
}
void add_clause(int x, int xval, int y, int yval){
x = x*2+xval;
y = y*2+yval;
G[x^1].pb(y);
G[y^1].pb(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]] = 0;
if(!dfs(i+1)) return 0;
}
}
}
return 1;
}
}solver;
bool test(int cnt, int n)
{
solver.init(cnt);
for(int i = 0; i < cnt; i++)
if(cb[i] != -1) solver.vis[2*i+cb[i]] = 1;
for(int u = 1; u <= n; u++){
for(int v : G0[u]) if(blo[v] != blo[u]){
int i = blo[v], j = blo[u], ci = col[v], cj = col[u];
solver.add_clause(i,ci,j,cj);
}
}
return solver.solve();
}
int main()
{
#ifdef LOCAL
freopen("input.txt","r",stdin);
#endif // LOCAL
int T;
scanf("%d",&T);
while(T--){
int n,m;
scanf("%d%d",&n,&m);
for(int i = 0; i <= n; i++) G0[i].clear(), G1[i].clear(), col[i] = cb[i] = -1;
for(int i = 1; i <= m; i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if(w == 0) {
G0[u].pb(v);
G0[v].pb(u);
continue;
}
G1[u].pb(v);
G1[v].pb(u);
}
bool flag = 1;
int cnt = 0;
for(int i = 1; i <= n; i++) if(col[i] == -1){
flag &= dfs(i,0,0,cnt);
++cnt;
}
for(int u = 1; u <= n; u++){
for(int v : G0[u]) if(blo[v] == blo[u]){
if(col[v] != col[u]) continue;
int b = blo[v];
if(cb[b] == -1){
cb[b] = col[v];
}
else{
flag &= (cb[b]==col[v]);
}
}
}
flag &= test(cnt,n);
if(flag) puts("YES");
else puts("NO");
}
return 0;
}