CodeForces 711D Directed Roads (DFS判环+计数)

题意:给定一个有向图,然后你可能改变某一些边的方向,然后就形成一种新图,让你求最多有多少种无环图。

析:假设这个图中没有环,那么有多少种呢?也就是说每一边都有两种放法,一共有2^x种,x是边数,那么如果有环呢?假设x是这个连通块的边数,

y是这个环的边数,那么就一共有2^x * (2 ^ y - 2) 种,减去这两种就是一边也不变,和所有的边都就变,这样就形成环了。

那么怎么计算呢?这个题的边很特殊,所以我们可以利用这个特征,我们在每个连通块时,用vis记录一下开始的父结点,用cnt记录每一个到每个点的深度,

然后如果产生环了,那么我们就可以很轻松的算出这个环的结点数,用当前的cnt减去就好,然后用sum记录一下环结点的总数,

最后用n减去环中的结点数,就剩下不是环的结点数了。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <list>
#include <sstream>
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;

typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const LL LNF = 0x3f3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 2e5 + 5;
const int mod = 1e9 + 7;
const int dr[] = {-1, 1, 0, 0, 1, 1, -1, -1};
const int dc[] = {0, 0, 1, -1, 1, -1, 1, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Min(int a, int b){ return a < b ? a : b; }
inline int Max(int a, int b){ return a > b ? a : b; }
inline LL Min(LL a, LL b){ return a < b ? a : b; }
inline LL Max(LL a, LL b){ return a > b ? a : b; }
inline bool is_in(int r, int c){
    return r >= 0 && r < n && c >= 0 && c < m;
}
int vis[maxn];
int a[maxn], cnt[maxn];
LL ans;
int sum;

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

void dfs(int d, int u, int fa){
    vis[u] = fa;
    cnt[u] = d;
    if(!vis[a[u]])  dfs(d+1, a[u], fa);
    else if(vis[a[u]] == fa){
        sum += cnt[u]-cnt[a[u]]+1;
        ans = (ans * (quick_pow(2LL, cnt[u]-cnt[a[u]]+1) - 2 + mod)) % mod;
    }
}

int main(){
    while(scanf("%d", &n) == 1){
        memset(vis, 0, sizeof vis);
        memset(cnt, 0, sizeof cnt);
        for(int i = 1; i <= n; ++i)  scanf("%d", &a[i]);

        ans = 1, sum = 0;
        for(int i = 1; i <= n; ++i){
            if(vis[i])  continue;
            dfs(0, i, i);
        }

        ans = (ans * quick_pow(2LL, n-sum)) % mod;
        cout << ans << endl;
    }
    return 0;
}
时间: 2024-11-24 15:02:35

CodeForces 711D Directed Roads (DFS判环+计数)的相关文章

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

Codeforces Round #369 (Div. 2) D. Directed Roads dfs求某个联通块的在环上的点的数量

D. Directed Roads ZS the Coder and Chris the Baboon has explored Udayland for quite some time. They realize that it consists of n towns numbered from 1to n. There are n directed roads in the Udayland. i-th of them goes from town i to some other town 

UVA818-Cutting Chains(二进制枚举+dfs判环)

Problem UVA818-Cutting Chains Accept:393  Submit:2087 Time Limit: 3000 mSec  Problem Description What a ?nd! Anna Locke has just bought several links of chain some of which may be connected. They are made from zorkium, a material that was frequently

2018 计蒜之道复赛 贝壳找房魔法师顾问(并查集+dfs判环)

贝壳找房在遥远的传奇境外,找到了一个强大的魔法师顾问.他有 22 串数量相同的法力水晶,每个法力水晶可能有不同的颜色.为了方便起见,可以将每串法力水晶视为一个长度不大于 10^5105,字符集不大于 10^5105 的字符串.现在魔法师想要通过一系列魔法使得这两个字符串相同.每种魔法形如 (u,\ v),\ u,\ v \le 10^5(u, v), u, v≤105,可以将一个字符 uu改成一个字符 vv,并且可以使用无限次.出于种种原因,魔法师会强行指定这两个串能否进行修改. 若失败输出 -

hdu4975 网络流解方程组(网络流+dfs判环或矩阵DP)

http://acm.hdu.edu.cn/showproblem.php?pid=4975 A simple Gaussian elimination problem. Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 579    Accepted Submission(s): 194 Problem Description Drag

hdu4888 Redraw Beautiful Drawings 最大流+判环

hdu4888 Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2007    Accepted Submission(s): 447 Problem Description Alice and Bob are playing together. Alice is crazy abou

CodeForces 937D 936B Sleepy Game 有向图判环,拆点,DFS

题意: 一种游戏,2个人轮流控制棋子在一块有向图上移动,每次移动一条边,不能移动的人为输,无限循环则为平局,棋子初始位置为$S$ 现在有一个人可以同时控制两个玩家,问是否能使得第一个人必胜,并输出一个解,否则判断是否能平局 题解: 看到这个题首先我想到了强连通分量,但是事实证明求出强连通分量,缩点对解决问题没有什么帮助.... 能写一些看似正确的算法,但其实是假算法来的.. ........... 所以应该先分析策略,肯定是能赢就赢,不能赢就求平局,最后才算输 平局很好判断,有向图上,从$S$点

CodeForces 659E New Reform (图的遍历判环)

Description Berland has n cities connected by m bidirectional roads. No road connects a city to itself, and each pair of cities is connected by no more than one road. It isnot guaranteed that you can get from any city to any other one, using only the

【dfs判负环】BZOJ1489: [HNOI2009]最小圈

Description 找出一个平均边权最小的圈. Solution 经典问题,二分答案判断有无负环. 但数据范围大,普通spfa会超时,于是用dfs判负环(快多了). 思路是dis设为0,枚举每个点u,如果d(u)+w<d(v)就搜v,如果搜到的节点曾搜到过说明找到了负环. 感慨一下dfs真是神奇. Code 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespac