gym101968 J. Restricted Vertex Cover
阿新 • • 發佈:2018-11-11
先二分圖染色,求出標號為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; }