我们有一颗从1到n编号的n个结点的树,此外,您将从树中获得M个节点对,形式为(a1,b1),(a2,b2),…(am,bm).
我们需要给每一条边定向,使得每一对节点对存在一条从ai到bi或从bi到ai的路径。
现在要求方案数,对10^9+7取mod即可。
对于前20%的数据,保证是一条链。
另有40%的数据,n,m<=5000
对于100%的数据,n,m<=300000
以前似乎见过这道题……然后就咕咕咕了……
一个十分显然的事实,固定根节点(1号节点)后,路径的方向只有向上和向下
不妨想到将链进行合并
对于一对关系(u,v),设它们的lca是d,那么就是将u~d合并,v~d合并(d的第一个儿子是最后合并)
处理完之后再合并(u,v),带权1
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 3e5 + 10; 4 5 struct REL { int a, b; } rel[N]; 6 7 int n, m; 8 9 int head[N], rest[N * 2], to[N * 2], tot; 10 11 void add(int u, int v) { to[++ tot] = v, rest[tot] = head[u], head[u] = tot; } 12 13 int fa[N][21], dep[N]; 14 15 void dfs(int u, int f) { 16 fa[u][0] = f, dep[u] = dep[f] + 1; 17 for(int i = head[u] ; i ; i = rest[i]) { 18 int v = to[i]; 19 if(v == f) continue; 20 dfs(v, u); 21 } 22 } 23 24 int getlca(int u, int v) { 25 if(dep[u] < dep[v]) swap(u, v); 26 for(int i = 20 ; ~ i ; -- i) if(dep[fa[u][i]] >= dep[v]) u = fa[u][i]; 27 if(u == v) return u; 28 for(int i = 20 ; ~ i ; -- i) if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i]; 29 return fa[u][0]; 30 } 31 32 int dis[N], acc[N]; 33 34 int get(int x) { 35 if(x == acc[x]) return x; 36 int y = acc[x]; 37 acc[x] = get(acc[x]); 38 dis[x] ^= dis[y]; 39 return acc[x]; 40 } 41 42 void merge(int a, int d) { 43 a = get(a); 44 while(dep[a] >= dep[d] + 2) { 45 acc[a] = get(fa[a][0]); 46 a = get(a); 47 } 48 } 49 50 const int p = 1e9 + 7; 51 typedef long long ll; 52 ll pw(ll a, ll b) { 53 ll r = 1; 54 for( ; b ; b >>= 1, a = a * a % p) if(b & 1) r = r * a % p; 55 return r; 56 } 57 58 int main() { 59 freopen("usmjeri.in", "r", stdin); 60 freopen("usmjeri.out", "w", stdout); 61 cin >> n >> m; 62 for(int i = 1, u, v ; i < n ; ++ i) { 63 cin >> u >> v; 64 add(u, v), add(v, u); 65 } 66 for(int i = 1 ; i <= n ; ++ i) acc[i] = i; 67 dfs(1, 0); 68 for(int j = 1 ; j <= 20 ; ++ j) 69 for(int i = 1 ; i <= n ; ++ i) 70 fa[i][j] = fa[fa[i][j - 1]][j - 1]; 71 for(int i = 1 ; i <= m ; ++ i) { 72 cin >> rel[i].a >> rel[i].b; 73 int a = rel[i].a, b = rel[i].b, d = getlca(a, b); 74 merge(a, d); 75 merge(b, d); 76 } 77 for(int i = 1 ; i <= m ; ++ i) { 78 int a = rel[i].a, b = rel[i].b, fa = get(a), fb = get(b), d = getlca(a, b); 79 if(d == a || d == b) continue; 80 if(fa == fb) { 81 if((dis[a] ^ dis[b]) == 0) { 82 puts("0"); 83 return 0; 84 } 85 } else { 86 dis[fa] = dis[a] ^ dis[b] ^ 1; 87 acc[fa] = get(b); 88 89 } 90 } 91 int ans = 0; 92 for(int i = 2 ; i <= n ; ++ i) { 93 ans += get(i) == i; 94 } 95 cout << pw(2, ans) << endl; 96 }