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 }
  • 相关阅读:
    Ubuntu 14.04 卸载通过源码安装的库
    Ubuntu 14.04 indigo 相关依赖
    Ubuntu 14.04 indigo 安装 cartographer 1.0.0
    Ubuntu 14.04 改变文件或者文件夹的拥有者
    安装cartographer遇到Unrecognized syntax identifier "proto3". This parser only recognizes "proto2"问题
    Unrecognized syntax identifier "proto3". This parser only recognizes "proto2". ”问题解决方法
    查看所有用户组,用户名
    1卸载ROS
    Ubuntu14.04 软件安装卸载
    Ubuntu14.04系统显示器不自动休眠修改
  • 原文地址:https://www.cnblogs.com/kirai/p/5820192.html
Copyright © 2011-2022 走看看