灰狼呼唤着同胞(brethren)
先求出确定边的联通块,有cnt块,显然方案数为2^(cnt-1)
联通块用dfs很好求
但此题还有并查集解法,且与一道叫团伙的题很像
边为0为敌人,1为朋友,敌人的敌人是朋友,朋友的朋友是朋友,正好对应本题情况
数据在管理里的文件
现附上dfs版(并查集还没写)
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #define mod (998244353) using namespace std; void read(int &x) { x=0;int f=1;char i=getchar(); while(i<'0'||i>'9'){if(i=='-')f=-1;i=getchar();} while(i>='0'&&i<='9'){x=x*10+i-'0';i=getchar();} x*=f; } int t,n,m; struct node { int next,to,dis; }edge[2000005]; int size,head[100005],color[100005],cnt; void putin(int from,int to,int dis) { size++; edge[size].to=to; edge[size].dis=dis; edge[size].next=head[from]; head[from]=size; } bool dfs(int r) { int i; bool ans=1; for(i=head[r];i!=-1;i=edge[i].next) { int y=edge[i].to; if(color[y]==-1) { if(edge[i].dis==0)color[y]=color[r]^1; else color[y]=color[r]; ans&=dfs(y); } else { if(edge[i].dis==0&&color[y]==color[r])return 0; if(edge[i].dis==1&&color[y]!=color[r])return 0; } } return ans; } int main() { freopen("brethren.in","r",stdin); freopen("brethren.out","w",stdout); int i,j; read(t);read(t); while(t--) { read(n);read(m); size=0;cnt=0; memset(head,-1,sizeof(head)); for(i=1;i<=m;i++) { int from,to,dis; read(from);read(to);read(dis); putin(from,to,dis); putin(to,from,dis); } for(i=1;i<=n;i++)color[i]=-1; bool flag=1; for(i=1;i<=n;i++) { if(color[i]==-1) { cnt++; color[i]=1; if(!dfs(i)){flag=0;break;} } } if(!flag)printf("0 "); else { int ans=1; for(i=1;i<cnt;i++) { ans=(ans*2)%mod; } printf("%d ",ans); } } return 0; }