您的位置:首页 > 其它

Codeforces 711 D. Directed Roads (DFS判环)

2016-08-30 17:54 399 查看
题目链接:http://codeforces.com/problemset/problem/711/D

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

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

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

//#pragma comment(linker, "/STACK:102400000, 102400000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
typedef __int64 LL;
typedef pair <int, int> P;
const int N = 2e5 + 5;
struct Edge {
int next, to;
}edge[N << 1];
LL mod = 1e9 + 7, d
, ans, f
, sum;
int head
, cnt;
bool vis
;

LL fpow(LL a, LL b) {
LL res = 1;
while(b) {
if(b & 1)
res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}

inline void add(int u, int v) {
edge[cnt].next = head[u];
edge[cnt].to = v;
head[u] = cnt++;
}

void dfs(int u, int p, int dep) {
if(!ans && vis[u]) {
ans = dep - d[u] ? dep - d[u] : 2;
return ;
} else if(vis[u]) {
return ;
}
d[u] = dep;
vis[u] = true;
++sum;
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(v == p)
continue;
dfs(v, u, dep + 1);
}
}

int main()
{
f[0] = 1;
for(int i = 1; i < N; ++i) {
f[i] = f[i - 1]*2LL % mod; //2的阶乘预处理
}
memset(head, -1, sizeof(head));
cnt = 0;
int n, u;
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &u);
add(u, i);
add(i, u);
}
LL res = 1;
for(int i = 1; i <= n; ++i) {
if(!vis[i]) {
ans = sum = 0;
dfs(i, -1, 1);
res = ((res * (f[ans] - 2) % mod + mod) % mod * f[sum - ans]) % mod;
}
}
printf("%lld\n", res);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: