灰狼呼唤着同胞(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 }

 

posted @ 2017-08-22 15:50  Z-Y-Y-S  阅读(448)  评论(0编辑  收藏  举报