Codeforces 711 D. Directed Roads (DFS判环)

题目链接:http://codeforces.com/problemset/problem/711/D

给你一个n个节点n条边的有向图,可以把一条边反向,现在问有多少种方式可以使这个图没有环。

每个连通量必然有一个环,dfs的时候算出连通量中点的个数y,算出连通量的环中点的个数x,所以这个连通量不成环的答案是2^(y - x) * (2^x - 2)。

最后每个连通量的答案相乘即可。

 1 //#pragma comment(linker, "/STACK:102400000, 102400000")
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <ctime>
10 #include <list>
11 #include <set>
12 #include <map>
13 using namespace std;
14 typedef __int64 LL;
15 typedef pair <int, int> P;
16 const int N = 2e5 + 5;
17 struct Edge {
18     int next, to;   
19 }edge[N << 1];
20 LL mod = 1e9 + 7, d[N], ans, f[N], sum;
21 int head[N], cnt;
22 bool vis[N];
23 
24 LL fpow(LL a, LL b) {
25     LL res = 1;
26     while(b) {
27         if(b & 1)
28             res = res * a % mod;
29         a = a * a % mod;
30         b >>= 1;
31     }
32     return res;
33 }
34 
35 inline void add(int u, int v) {
36     edge[cnt].next = head[u];
37     edge[cnt].to = v;
38     head[u] = cnt++;
39 }
40 
41 void dfs(int u, int p, int dep) {
42     if(!ans && vis[u]) {
43         ans = dep - d[u] ? dep - d[u] : 2;
44         return ;
45     } else if(vis[u]) {
46         return ;
47     }
48     d[u] = dep;
49     vis[u] = true;
50     ++sum;
51     for(int i = head[u]; ~i; i = edge[i].next) {
52         int v = edge[i].to;
53         if(v == p)
54             continue;
55         dfs(v, u, dep + 1);
56     }
57 }
58 
59 int main()
60 {
61     f[0] = 1;
62     for(int i = 1; i < N; ++i) {
63         f[i] = f[i - 1]*2LL % mod; //2的阶乘预处理
64     }
65     memset(head, -1, sizeof(head));
66     cnt = 0;
67     int n, u;
68     scanf("%d", &n);
69     for(int i = 1; i <= n; ++i) {
70         scanf("%d", &u);
71         add(u, i);
72         add(i, u);
73     }
74     LL res = 1;
75     for(int i = 1; i <= n; ++i) {
76         if(!vis[i]) {
77             ans = sum = 0;
78             dfs(i, -1, 1);
79             res = ((res * (f[ans] - 2) % mod + mod) % mod * f[sum - ans]) % mod;
80         }
81     }
82     printf("%lld\n", res);
83     return 0;
84 }
View Code

 

posted @ 2016-08-30 17:54  Recoder  阅读(388)  评论(0编辑  收藏  举报