题解
- 发现,对于一对点(ai,bi)
- 只要其中一条被确定了,其它都被确定了,而且黄色和红色的方向相反
- 可以用并差集,两个点之间有关系的可以打入同一个并差集里
- 这样最后的答案就是2^并差集的个数
- 其中,并差集要按秩合并
- 现在,考虑一下0的情况
- 在维护并差集时还要维护一个信息,就是当前方向与父亲的方向是否相反,这个异或一下就好了
- 那么对于两个点(a,b),如果要使它们可行,它们的路径要相反
- 因为,按照并差集每次会将下面的某个点连到最上面的祖先,那么求会产生上图(ai,bi)的情况
- 就要方向相反
代码
1 #include <cstdio>
2 #include <iostream>
3 #include <cstring>
4 using namespace std;
5 const long long mo=1e9+7;
6 struct edge {int to,from; }e[300010*2];
7 int fa[300010],p[300010][3],f[300010][20],deep[300010],w[300010],head[300010],cnt,n,m;
8 bool boo;
9 void insert(int x,int y) { e[++cnt].to=y; e[cnt].from=head[x]; head[x]=cnt; }
10 void dfs(int x,int fa)
11 {
12 deep[x]=deep[fa]+1;
13 for (int i=head[x];i;i=e[i].from)
14 {
15 int v=e[i].to;
16 if (v==fa) continue;
17 f[v][0]=x;
18 dfs(v,x);
19 }
20 }
21 int getlca(int x,int y)
22 {
23 if (deep[x]>deep[y]) swap(x,y);
24 for (int i=18;i>=0;i--)
25 if (deep[f[y][i]]>=deep[x])
26 y=f[y][i];
27 if (x==y) return x;
28 for (int i=18;i>=0;i--)
29 if (f[x][i]!=f[y][i])
30 x=f[x][i],y=f[y][i];
31 return f[x][0];
32 }
33 int getfather(int x)
34 {
35 if (fa[x]==x) return x;
36 int d=fa[x];
37 fa[x]=getfather(fa[x]);
38 w[x]=w[x]^w[d];
39 return fa[x];
40 }
41 void together(int x,int lca)
42 {
43 x=getfather(x);
44 while (deep[x]-2>=deep[lca])
45 {
46 int v=f[x][0];
47 v=getfather(v);
48 fa[x]=v;
49 x=getfather(x);
50 }
51 }
52 int main()
53 {
54 freopen("usmjeri.in","r",stdin);
55 freopen("usmjeri.out","w",stdout);
56 scanf("%d%d",&n,&m);
57 for (int i=1;i<=n-1;i++)
58 {
59 int u,v;
60 scanf("%d%d",&u,&v);
61 insert(u,v),insert(v,u);
62 }
63 dfs(1,0); f[1][0]=1;
64 for (int i=1;i<=18;i++)
65 for (int j=1;j<=n;j++)
66 f[j][i]=f[f[j][i-1]][i-1];
67 for (int i=1;i<=n;i++) fa[i]=i;
68 for (int i=1;i<=m;i++)
69 {
70 int u,v;
71 scanf("%d%d",&u,&v);
72 int lca=getlca(u,v);
73 together(u,lca),together(v,lca);
74 p[i][0]=u,p[i][1]=v,p[i][2]=lca;
75 }
76 boo=1;
77 for (int i=1;i<=m;i++)
78 {
79 int x=p[i][0],y=p[i][1],lca=p[i][2];
80 if (x==lca||y==lca) continue;
81 int u=getfather(x),v=getfather(y);
82 if (u==v)
83 {
84 if ((w[x]^w[y])!=1)
85 {
86 printf("0");
87 return 0;
88 }
89 continue;
90 }
91 fa[u]=v,w[u]=1^w[y]^w[x];
92 }
93 int ans=1;
94 for (int i=2;i<=n;i++)
95 {
96 getfather(i);
97 if (fa[i]==i) (ans*=2)%=mo;
98 }
99 printf("%d",ans);
100 return 0;
101 }