zoukankan      html  css  js  c++  java
  • [CF711D]Directed Roads(强联通分量,计数)

    题目链接: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次。

      1 #include <algorithm>
      2 #include <iostream>
      3 #include <iomanip>
      4 #include <cstring>
      5 #include <climits>
      6 #include <complex>
      7 #include <fstream>
      8 #include <cassert>
      9 #include <cstdio>
     10 #include <bitset>
     11 #include <vector>
     12 #include <deque>
     13 #include <queue>
     14 #include <stack>
     15 #include <ctime>
     16 #include <set>
     17 #include <map>
     18 #include <cmath>
     19 using namespace std;
     20 #define fr first
     21 #define sc second
     22 #define cl clear
     23 #define BUG puts("here!!!")
     24 #define W(a) while(a--)
     25 #define pb(a) push_back(a)
     26 #define Rint(a) scanf("%d", &a)
     27 #define Rll(a) scanf("%I64d", &a)
     28 #define Rs(a) scanf("%s", a)
     29 #define Cin(a) cin >> a
     30 #define FRead() freopen("in", "r", stdin)
     31 #define FWrite() freopen("out", "w", stdout)
     32 #define Rep(i, len) for(int i = 0; i < (len); i++)
     33 #define For(i, a, len) for(int i = (a); i < (len); i++)
     34 #define Cls(a) memset((a), 0, sizeof(a))
     35 #define Clr(a, x) memset((a), (x), sizeof(a))
     36 #define Full(a) memset((a), 0x7f7f7f, sizeof(a))
     37 #define lrt rt << 1
     38 #define rrt rt << 1 | 1
     39 #define pi 3.14159265359
     40 #define RT return
     41 #define lowbit(x) x & (-x)
     42 #define onecnt(x) __builtin_popcount(x)
     43 typedef long long LL;
     44 typedef long double LD;
     45 typedef unsigned long long ULL;
     46 typedef pair<int, int> pii;
     47 typedef pair<string, int> psi;
     48 typedef pair<LL, LL> pll;
     49 typedef map<string, int> msi;
     50 typedef vector<int> vi;
     51 typedef vector<LL> vl;
     52 typedef vector<vl> vvl;
     53 typedef vector<bool> vb;
     54 
     55 const int maxn = 200200;
     56 const LL mod = 1e9+7;
     57 LL ret;
     58 
     59 typedef struct Edge {
     60     int u;
     61     int v;
     62     int next;
     63     Edge() { next = -1; }
     64 }Edge;
     65 
     66 int head[maxn], ecnt;
     67 Edge edge[maxn];
     68 int n, m;
     69 
     70 int bcnt, dindex;
     71 int dfn[maxn], low[maxn];
     72 int stk[maxn], top;
     73 int belong[maxn];
     74 int in[maxn], out[maxn];
     75 bool instk[maxn];
     76 int cnt[maxn];
     77 
     78 void init() {
     79     memset(edge, 0, sizeof(edge));
     80     memset(head, -1, sizeof(head));
     81     memset(instk, 0, sizeof(instk));
     82     memset(dfn, 0, sizeof(dfn));
     83     memset(low, 0, sizeof(low));
     84     memset(belong, 0, sizeof(belong));
     85     memset(in, 0, sizeof(in));
     86     memset(out, 0, sizeof(out));
     87     ecnt = top = bcnt = dindex = 0;
     88 }
     89 
     90 void adde(int uu, int vv) {
     91     edge[ecnt].u = uu;
     92     edge[ecnt].v = vv;
     93     edge[ecnt].next = head[uu];
     94     head[uu] = ecnt++;
     95 }
     96 
     97 void tarjan(int u) {
     98     int v = u;
     99     dfn[u] = low[u] = ++dindex;
    100     stk[++top] = u;
    101     instk[u] = 1;
    102     for(int i = head[u]; ~i; i=edge[i].next) {
    103         v = edge[i].v;
    104         if(!dfn[v]) {
    105             tarjan(v);
    106             low[u] = min(low[u], low[v]);
    107         }
    108         else if(instk[v]) low[u] = min(low[u], dfn[v]);
    109     }
    110     if(dfn[u] == low[u]) {
    111         bcnt++;
    112         do {
    113             v = stk[top--];
    114             instk[v] = 0;
    115             belong[v] = bcnt;
    116             cnt[bcnt]++;
    117         } while(v != u);
    118     }
    119 }
    120 
    121 LL quickmul(LL x, LL n) {
    122     LL ans = 1;
    123     while(n) {
    124         if(n & 1) ans = (ans * x) % mod;
    125         x = x * x % mod;
    126         n >>= 1;
    127     }
    128     return ans;
    129 }
    130 
    131 
    132 int main() {
    133     // FRead();
    134     while(~Rint(n)) {
    135         ret = 1; Cls(cnt);
    136         init();
    137         int v;
    138         For(i, 1, n+1) {
    139             Rint(v);
    140             adde(i, v);
    141         }
    142         For(i, 1, n+1) if(!dfn[i]) tarjan(i);
    143         LL tmp = 0;
    144         For(i, 1, bcnt+1) {
    145             if(cnt[i] > 1) {
    146                 ret = (ret * (quickmul(2, cnt[i])-2+mod))%mod;
    147                 tmp = (tmp + cnt[i]) % mod;
    148             }
    149         }
    150         ret = (ret * quickmul(2, n-tmp)) % mod;
    151         cout << ret << endl;
    152     }
    153     RT 0;
    154 }
  • 相关阅读:
    设计模式
    Junit单元测试
    数组存储和链表存储
    java新特型
    List&&Set
    Map
    File文件
    1588. 所有奇数长度子数组的和
    2秒后跳转到某页面
    图片轮播/倒计时--windows对象(setInterval)
  • 原文地址:https://www.cnblogs.com/kirai/p/5820192.html
Copyright © 2011-2022 走看看