[CF711D]Directed Roads(强联通分量,计数)
2016-08-29 23:36
387 查看
题目链接:http://codeforces.com/contest/711/problem/D
题意:n个点n条边的有向图,每个点都指向另外一个点,要翻转其中的几条边,问有多少种翻转方式可以使这张图没有环存在。
可以先求强联通分量,由于题目的特殊性,每个点只有一个出边,所以加入一个强联通分量至少有两个点,则每一个强联通分量中必定有且仅有只有一个环。我们考虑如何翻转这个环内的边,使得生成的数量一共有C(x,1)+C(x,2)+...+C(x,x)=2^x-1种,除去全部翻转的C(x,x),则还剩下2^x-2种。则所有点数大于2强联通分量内一共有Σ(2^xi-2)种。
再考虑一个出边的强联通分量,无论如何翻转都是没有问题的,则一共可以翻转2^y次。
则总共可以翻转(Σ(2^xi-2))*2^y次。
题意:n个点n条边的有向图,每个点都指向另外一个点,要翻转其中的几条边,问有多少种翻转方式可以使这张图没有环存在。
可以先求强联通分量,由于题目的特殊性,每个点只有一个出边,所以加入一个强联通分量至少有两个点,则每一个强联通分量中必定有且仅有只有一个环。我们考虑如何翻转这个环内的边,使得生成的数量一共有C(x,1)+C(x,2)+...+C(x,x)=2^x-1种,除去全部翻转的C(x,x),则还剩下2^x-2种。则所有点数大于2强联通分量内一共有Σ(2^xi-2)种。
再考虑一个出边的强联通分量,无论如何翻转都是没有问题的,则一共可以翻转2^y次。
则总共可以翻转(Σ(2^xi-2))*2^y次。
#include <algorithm> #include <iostream> #include <iomanip> #include <cstring> #include <climits> #include <complex> #include <fstream> #include <cassert> #include <cstdio> #include <bitset> #include <vector> #include <deque> #include <queue> #include <stack> #include <ctime> #include <set> #include <map> #include <cmath> using namespace std; #define fr first #define sc second #define cl clear #define BUG puts("here!!!") #define W(a) while(a--) #define pb(a) push_back(a) #define Rint(a) scanf("%d", &a) #define Rll(a) scanf("%I64d", &a) #define Rs(a) scanf("%s", a) #define Cin(a) cin >> a #define FRead() freopen("in", "r", stdin) #define FWrite() freopen("out", "w", stdout) #define Rep(i, len) for(int i = 0; i < (len); i++) #define For(i, a, len) for(int i = (a); i < (len); i++) #define Cls(a) memset((a), 0, sizeof(a)) #define Clr(a, x) memset((a), (x), sizeof(a)) #define Full(a) memset((a), 0x7f7f7f, sizeof(a)) #define lrt rt << 1 #define rrt rt << 1 | 1 #define pi 3.14159265359 #define RT return #define lowbit(x) x & (-x) #define onecnt(x) __builtin_popcount(x) typedef long long LL; typedef long double LD; typedef unsigned long long ULL; typedef pair<int, int> pii; typedef pair<string, int> psi; typedef pair<LL, LL> pll; typedef map<string, int> msi; typedef vector<int> vi; typedef vector<LL> vl; typedef vector<vl> vvl; typedef vector<bool> vb; const int maxn = 200200; const LL mod = 1e9+7; LL ret; typedef struct Edge { int u; int v; int next; Edge() { next = -1; } }Edge; int head[maxn], ecnt; Edge edge[maxn]; int n, m; int bcnt, dindex; int dfn[maxn], low[maxn]; int stk[maxn], top; int belong[maxn]; int in[maxn], out[maxn]; bool instk[maxn]; int cnt[maxn]; void init() { memset(edge, 0, sizeof(edge)); memset(head, -1, sizeof(head)); memset(instk, 0, sizeof(instk)); memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(belong, 0, sizeof(belong)); memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); ecnt = top = bcnt = dindex = 0; } void adde(int uu, int vv) { edge[ecnt].u = uu; edge[ecnt].v = vv; edge[ecnt].next = head[uu]; head[uu] = ecnt++; } void tarjan(int u) { int v = u; dfn[u] = low[u] = ++dindex; stk[++top] = u; instk[u] = 1; for(int i = head[u]; ~i; i=edge[i].next) { v = edge[i].v; if(!dfn[v]) { tarjan(v); low[u] = min(low[u], low[v]); } else if(instk[v]) low[u] = min(low[u], dfn[v]); } if(dfn[u] == low[u]) { bcnt++; do { v = stk[top--]; instk[v] = 0; belong[v] = bcnt; cnt[bcnt]++; } while(v != u); } } LL quickmul(LL x, LL n) { LL ans = 1; while(n) { if(n & 1) ans = (ans * x) % mod; x = x * x % mod; n >>= 1; } return ans; } int main() { // FRead(); while(~Rint(n)) { ret = 1; Cls(cnt); init(); int v; For(i, 1, n+1) { Rint(v); adde(i, v); } For(i, 1, n+1) if(!dfn[i]) tarjan(i); LL tmp = 0; For(i, 1, bcnt+1) { if(cnt[i] > 1) { ret = (ret * (quickmul(2, cnt[i])-2+mod))%mod; tmp = (tmp + cnt[i]) % mod; } } ret = (ret * quickmul(2, n-tmp)) % mod; cout << ret << endl; } RT 0; }
相关文章推荐
- 【线段树合并】联通分量计数
- [Codeforces Round #369 (Div. 2)D. Directed Roads]Tarjan强连通分量+组合计数
- [ARC062]F - Painting Graphs with AtCoDeer 双联通分量+Pólya计数
- 51Nod-1811-联通分量计数
- 51nod 1811 联通分量计数
- board (双联通分量)
- [省选前题目整理][POJ 2942]Knights of the Round Table(Tarjan求点双联通分量+DFS对环染色)
- 【BZOJ】1512 [POI2006]Pro-Professor Szu 强联通分量+拓扑
- poj3352 边-双联通分量
- poj 2117 求割点+联通分量个数
- 有向图求强联通分量
- POJ2942 Knights of the Round Table(双联通分量+奇圈判断)
- BZOJ 1093 ZJOI 2007 最大半连通子图 强联通分量+拓扑图DP
- HDU 1269 迷宫城堡 强联通分量模板存放处
- HDU 4738 双联通分量
- bzoj 2438: [中山市选2011]杀人游戏 (强联通分量 Tarjan)
- 【BZOJ2730】【codevs1996】矿场建设,点双联通分量
- 强联通分量
- tanjan算法求强联通分量
- 2016 天梯赛决赛试题 L2-013. 红色警报 (判断联通分量个数)