Codeforces 859E Desk Disorder 并查集找环,乘法原理
2017-09-20 19:14
507 查看
题目链接:http://codeforces.com/contest/859/problem/E
题意:有N个人。2N个座位。现在告诉你这N个人它们现在的座位。以及它们想去的座位。每个人可以去它们想去的座位或者就站在原地不动。新的座位和旧的座位,都不允许一个座位被两个人占据的情况。问你安排的方案数。
解法:对于这N个点,N条边构成的图,我们应该对每个连通块独立计算答案,最后乘起来。如果n个点,n-1条边答案显然为n。如果n个点n条边,会出现一个环,且恰好只有一个环。如果是一个自环,那么答案是1,因为所有人都不能动。如果环的大小>=2的话,答案为2。
维护环直接用并查集即可。
#include <bits/stdc++.h> using namespace std; const int maxn = 200010; const int mod = 1e9+7; namespace DSU{ int fa[maxn], cycle[maxn], sz[maxn]; void init(){ for(int i=1; i<maxn; i++) fa[i] = i, sz[i] = 1, cycle[i] = 0; } int find_set(int x){ if(x == fa[x]) return x; else return fa[x] = find_set(fa[x]); } void union_set(int x, int y){ int fx = find_set(x); int fy = find_set(y); if(fx == fy){ cycle[fx] = 1; }else{ fa[fy] = fx; sz[fx] += sz[fy]; cycle[fx] |= cycle[fy]; } } } using namespace DSU; int main() { int n; cin >> n; init(); long long ans = 1; for(int i=1; i<=n; i++){ int x, y; cin >> x >> y; if(x == y){ cycle[find_set(x)] = 2; continue; } union_set(x, y); } for(int i=1; i<=2*n; i++){ if(find_set(i) == i){ if(cycle[i] == 1) ans = ans*2%mod; else{ if(cycle[i] == 0) ans = ans * sz[i]%mod; } } } cout << ans << endl; return 0; }
相关文章推荐
- CodeForces - 893C Rumor(并查集,DFS)
- Codeforces 455C —— Civilization(并查集,树上最长链)
- Codeforces_764_C. Timofey and a tree_(并查集)(dfs)
- CodeForces 277A Learning Languages 并查集
- 【并查集分块】Codeforces 475D CGCDSSQ
- CodeForces 123A 并查集
- CodeForces 151D Quantity of Strings(并查集)
- CodeForces - 731C Socks (并查集+贪心)
- Codeforces 734E Anton and Tree【并查集缩点||DFS缩点+树的直径】
- CodeForces - 731C Socks(并查集)(贪心)
- Codeforces 160D Edges in MST【思维+并查集+求桥(有重边)】
- CodeForces - 698B Fix a Tree(并查集)
- Codeforces 500B:New Year Permutation(并查集||Floyd+思维)
- codeforces 722C 并查集好题+逆序处理
- CODEFORCES 468B Two Sets ---并查集建树
- codeforces 469D. Two Sets(贪心or并查集)
- codeforces 445 B. DZY Loves Chemistry (并查集)
- codeforces 691D Swaps in Permutation(并查集)
- 二维并查集-CodeForces 505BMr. Kitayuta's Colorful Graph
- codeforces-755【C思维、并查集】