灰狼呼唤着同胞(brethren)
先求出确定边的联通块,有cnt块,显然方案数为2^(cnt-1)
联通块用dfs很好求
但此题还有并查集解法,且与一道叫团伙的题很像
边为0为敌人,1为朋友,敌人的敌人是朋友,朋友的朋友是朋友,正好对应本题情况
数据在管理里的文件
现附上dfs版(并查集还没写)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 struct Node 7 { 8 int next,to,dis; 9 }edge[2000001]; 10 int head[100001],num,col[100001],n,m,cnt; 11 long long ans; 12 bool ok; 13 void add(int u,int v,int d) 14 { 15 num++; 16 edge[num].next=head[u]; 17 head[u]=num; 18 edge[num].to=v; 19 edge[num].dis=d; 20 } 21 void dfs(int x) 22 {int i,j; 23 for (i=head[x];i;i=edge[i].next) 24 { 25 int v=edge[i].to; 26 if (col[v]==-1) 27 { 28 if (edge[i].dis==0) col[v]=col[x]^1,dfs(v); 29 else col[v]=col[x],dfs(v); 30 } 31 else 32 { 33 if (edge[i].dis==0&&col[v]==col[x]) ok=0; 34 if (edge[i].dis&&col[v]!=col[x]) ok=0; 35 } 36 } 37 } 38 int main() 39 {int Test,T,i,u,v,d; 40 cin>>Test>>T; 41 while (T--) 42 {num=0;cnt=0; 43 memset(head,0,sizeof(head)); 44 scanf("%d%d",&n,&m); 45 for (i=1;i<=m;i++) 46 { 47 scanf("%d%d%d",&u,&v,&d); 48 add(u,v,d); 49 add(v,u,d); 50 } 51 for (i=1;i<=n;i++) col[i]=-1; 52 ok=1; 53 for (i=1;i<=n;i++) 54 if (col[i]==-1) 55 { 56 cnt++; 57 col[i]=0; 58 dfs(i); 59 } 60 ans=1; 61 if (!ok) printf("0\n"); 62 else 63 { 64 for (i=1;i<=cnt-1;i++) 65 ans=(ans*2)%998244353; 66 printf("%lld\n",ans); 67 } 68 } 69 }