其实二分图染色问题可以看成2-SAT问题的一个特例,只需要稍微修改一下板子,在对每个连通块dfs的时候每个点黑白都试一下,取个最小值即可,因为二分图染色比较特殊,各个连通块相互独立,因此不存在回溯的问题(一般情况下2-SAT问题对每个点的黑白染色都分别判断的话需要回溯)
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef double db; 5 const int N=2e5+10,inf=0x3f3f3f3f; 6 struct TWO_SAT { 7 int n,hd[N],ne,col[N],sta[N],tp; 8 struct E {int v,f,g,nxt;} e[N*4]; 9 void link(int u,int v,int f,int g) { 10 e[ne]= {v,f,g,hd[u]},hd[u]=ne++; 11 e[ne]= {u,!g,!f,hd[v]},hd[v]=ne++; 12 } 13 void init(int _n) { 14 n=_n,ne=tp=0; 15 for(int i=1; i<=n; ++i)hd[i]=-1; 16 } 17 bool dfs(int u,int c) { 18 if(~col[u])return col[u]==c; 19 col[u]=c,sta[tp++]=u; 20 for(int i=hd[u]; ~i; i=e[i].nxt) { 21 int v=e[i].v,f=e[i].f,g=e[i].g; 22 if(f==col[u]&&!dfs(v,g))return 0; 23 } 24 return 1; 25 } 26 int check() { 27 int ret=0; 28 for(int i=1; i<=n; ++i)col[i]=-1; 29 for(int i=1; i<=n; ++i)if(!~col[i]) { 30 tp=0; 31 int mi=inf; 32 if(dfs(i,0)) { 33 int cnt=0; 34 for(int i=0; i<tp; ++i)if(col[sta[i]]==1)++cnt; 35 mi=min(mi,cnt); 36 } 37 for(; tp; col[sta[--tp]]=-1); 38 if(dfs(i,1)) { 39 int cnt=0; 40 for(int i=0; i<tp; ++i)if(col[sta[i]]==1)++cnt; 41 mi=min(mi,cnt); 42 } else { 43 for(; tp; col[sta[--tp]]=-1); 44 dfs(i,0); 45 } 46 if(mi==inf)return -1; 47 ret+=mi; 48 } 49 return ret; 50 } 51 } twosat; 52 int n,m; 53 54 int main() { 55 scanf("%d%d",&n,&m); 56 twosat.init(n); 57 while(m--) { 58 int u,v,c; 59 scanf("%d%d%d",&u,&v,&c); 60 if(c==0)twosat.link(u,u,1,0),twosat.link(v,v,1,0); 61 else if(c==1)twosat.link(u,v,1,0),twosat.link(u,v,0,1); 62 else if(c==2)twosat.link(u,u,0,1),twosat.link(v,v,0,1); 63 } 64 int ans=twosat.check(); 65 if(ans==-1)puts("impossible"); 66 else printf("%d ",ans); 67 return 0; 68 }