[关闭]
@ZCDHJ 2019-10-25T00:06:03.000000Z 字数 855 阅读 554

Codeforces859E Desk Disorder


考虑一种比较特殊的连边方式:每个原来的座位连向新的座位。

可以发现不同连通块之间没有影响,所以分别计算答案。对于一个连通块,因为图中所有点的出度小于等于 的缘故,只有可能是一棵树或者一棵基环树。对于树的情况,只有树的大小种可能(枚举哪个点没有被坐)。对于基环树的情况,将环与树剖分开来看,树只有一种可能,而环只有两种可能,所以基环树的情况的总方案数是

并查集维护即可。

  1. #include <iostream>
  2. #include <cstdio>
  3. const int MAXN = 1e5;
  4. const int MOD = 1e9 + 7;
  5. int n, ans;
  6. int father[MAXN << 1 | 1], size[MAXN << 1 | 1];
  7. bool vis[MAXN << 1 | 1];
  8. inline int read() {
  9. register int x = 0;
  10. register char ch = getchar();
  11. while (!isdigit(ch)) ch = getchar();
  12. while (isdigit(ch)) {
  13. x = x * 10 + ch - '0';
  14. ch = getchar();
  15. }
  16. return x;
  17. }
  18. int find(int x) {
  19. return father[x] == x ? x : father[x] = find(father[x]);
  20. }
  21. int main() {
  22. n = read();
  23. for (int i = 1; i <= 2 * n; ++i) father[i] = i, size[i] = 1;
  24. ans = 1;
  25. for (int i = 1; i <= n; ++i) {
  26. int u = read(), v = read();
  27. vis[u] = 1;
  28. if (u == v) continue;
  29. int U = find(u), V = find(v);
  30. if (U == V) {
  31. ans = 1LL * ans * 2 % MOD;
  32. }
  33. size[V] += size[U];
  34. father[U] = V;
  35. }
  36. for (int i = 1; i <= 2 * n; ++i) {
  37. if (!vis[i]) ans = 1LL * ans * size[i] % MOD;
  38. }
  39. printf("%d\n", ans);
  40. return 0;
  41. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注