zoukankan      html  css  js  c++  java
  • HDU-2767-tarjan/Kosaraju求scc

    http://acm.hdu.edu.cn/showproblem.php?pid=2767

    问最少添加几条边使得图为强连通。

      tarjan跑一下,然后对强连通分量缩点,找下此时出度为零和入度为零的点数输出较大者即可。

      tarjan,dfn数组也同时起到了标记的作用,如果未标记说明此时的边就是dfs树上的边,否则的话,如果v已经处于某个scc中说明这条边是交叉边,不用考虑(因为一定无对应的回边,有的话这个点就应该和v属于同一个scc,与过程矛盾)。否则就是回边了,和求桥和割点的方法类似求dfn以及low数组。

      最后如果low[u]==dfn[u]说明u沿着他的孩子能回到他自己,这就形成了一个环,环上的所有点构成了一个scc,不断出栈直到u出现为止统计下scc。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<map>
      5 #include<set>
      6 #include<stack>
      7 #include<deque>
      8 #include<bitset>
      9 #include<unordered_map>
     10 #include<unordered_set>
     11 #include<queue>
     12 #include<cstdlib>
     13 #include<ctype.h>
     14 #include<ctime>
     15 #include<functional>
     16 #include<algorithm>
     17 #include<bits/stdc++.h>
     18 using namespace std;
     19 #define LL long long 
     20 #define pii pair<int,int>
     21 #define mp make_pair
     22 #define pb push_back
     23 #define fi first
     24 #define se second
     25 #define inf 0x3f3f3f3f
     26 #define debug puts("debug")
     27 #define mid ((L+R)>>1)
     28 #define lc (id<<1)
     29 #define rc (id<<1|1)
     30 const int maxn=20020;
     31 const int maxm=200020;
     32 const double PI=acos(-1.0);
     33 const double eps=1e-6;
     34 const LL mod=1e9+7;
     35 LL gcd(LL a,LL b){return b==0?a:gcd(b,a%b);}
     36 LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
     37 LL qpow(LL a,LL b,LL c){LL r=1; for(;b;b>>=1,a=a*a%c)if(b&1)r=r*a%c;return r;}
     38 template<class T>
     39 void prt(T v){for(auto x:v)cout<<x<<' ';cout<<endl;}
     40 struct Edge{int u,v,w,next;};
     41 
     42 int dfn[maxn],low[maxn],scc[maxn],scc_cnt,sum;
     43 int in[maxn],out[maxn];
     44 vector<int>g[maxn];
     45 stack<int>S;
     46 void dfs(int u){
     47     dfn[u]=low[u]=++sum;
     48     S.push(u);
     49     for(int v:g[u]){
     50         if(!dfn[v]){
     51             dfs(v);
     52             low[u]=min(low[u],low[v]);
     53         }else if(!scc[v]){
     54             low[u]=min(low[u],dfn[v]);
     55         }
     56     }
     57     if(dfn[u]==low[u]){
     58         ++scc_cnt;
     59         int x=-1;
     60         for(;;){
     61             x=S.top();S.pop();
     62             scc[x]=scc_cnt;
     63             if(x==u)break;
     64         }
     65     }
     66 }
     67 int main(){
     68     int t,n,m,i,j,k,u,v;
     69     scanf("%d",&t);
     70     while(t--){
     71         scanf("%d%d",&n,&m);
     72         for(i=1;i<=n;++i)g[i].clear(),dfn[i]=low[i]=scc[i]=0;
     73         sum=scc_cnt=0;
     74         while(!S.empty())S.pop();
     75         while(m--){
     76             scanf("%d%d",&u,&v);
     77             g[u].pb(v);
     78         }
     79         for(i=1;i<=n;++i){
     80             if(!dfn[i]){
     81                 dfs(i);
     82             }
     83         }
     84         if(scc_cnt==1){
     85             cout<<0<<endl;
     86             continue;
     87         }
     88         for(i=1;i<=scc_cnt;++i)in[i]=out[i]=1;
     89         for(u=1;u<=n;++u){
     90             for(int v:g[u]){
     91                 if(scc[u]!=scc[v]){
     92                     in[scc[v]]=out[scc[u]]=0;
     93                 }
     94             }
     95         }
     96         int a=0,b=0;
     97         for(i=1;i<=scc_cnt;++i)a+=in[i],b+=out[i];
     98         cout<<max(a,b)<<endl;
     99     }
    100     return 0;
    101 }

    Kosaraju:先按原图跑一编按后序顺序编号,然后按照编号从大到小跑反向图,跑一次就是一个scc。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<map>
     5 #include<set>
     6 #include<stack>
     7 #include<deque>
     8 #include<bitset>
     9 #include<unordered_map>
    10 #include<unordered_set>
    11 #include<queue>
    12 #include<cstdlib>
    13 #include<ctype.h>
    14 #include<ctime>
    15 #include<functional>
    16 #include<algorithm>
    17 #include<bits/stdc++.h>
    18 using namespace std;
    19 #define LL long long 
    20 #define pii pair<int,int>
    21 #define mp make_pair
    22 #define pb push_back
    23 #define fi first
    24 #define se second
    25 #define inf 0x3f3f3f3f
    26 #define debug puts("debug")
    27 #define mid ((L+R)>>1)
    28 #define lc (id<<1)
    29 #define rc (id<<1|1)
    30 const int maxn=20020;
    31 const int maxm=200020;
    32 const double PI=acos(-1.0);
    33 const double eps=1e-6;
    34 const LL mod=1e9+7;
    35 LL gcd(LL a,LL b){return b==0?a:gcd(b,a%b);}
    36 LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
    37 LL qpow(LL a,LL b,LL c){LL r=1; for(;b;b>>=1,a=a*a%c)if(b&1)r=r*a%c;return r;}
    38 template<class T>
    39 void prt(T v){for(auto x:v)cout<<x<<' ';cout<<endl;}
    40 struct Edge{int u,v,w,next;};
    41 
    42 int vis[maxn],scc[maxn],scc_cnt;
    43 int in[maxn],out[maxn];
    44 vector<int>g[maxn],g2[maxn],q;
    45 void dfs1(int u){
    46     if(vis[u])return;vis[u]=1;
    47     for(int v:g[u])dfs1(v);q.pb(u);
    48 }
    49 void dfs2(int u){
    50     if(scc[u])return;scc[u]=scc_cnt;
    51     for(int v:g2[u])dfs2(v);
    52 }
    53 int main(){
    54     int t,n,m,i,j,k,u,v;
    55     scanf("%d",&t);
    56     while(t--){
    57         scanf("%d%d",&n,&m);
    58         q.clear();
    59         for(i=1;i<=n;++i)g[i].clear(),g2[i].clear(),vis[i]=scc[i]=0;
    60         scc_cnt=0;
    61         while(m--){
    62             scanf("%d%d",&u,&v);
    63             g[u].pb(v);
    64             g2[v].pb(u);
    65         }
    66         for(i=1;i<=n;++i){
    67             if(!vis[i]){
    68                 dfs1(i);
    69             }
    70         }
    71         for(i=n-1;i>=0;--i){
    72             if(!scc[q[i]]){
    73                 ++scc_cnt;
    74                 dfs2(q[i]);
    75             }
    76         }
    77     //    cout<<"FUCK: "<<scc_cnt<<endl;
    78          if(scc_cnt==1){
    79             cout<<0<<endl;
    80             continue;
    81         }
    82         for(i=1;i<=scc_cnt;++i)in[i]=out[i]=1;
    83         for(u=1;u<=n;++u){
    84             for(int v:g[u]){
    85                 if(scc[u]!=scc[v]){
    86                     in[scc[v]]=out[scc[u]]=0;
    87                 }
    88             }
    89         }
    90         int a=0,b=0;
    91         for(i=1;i<=scc_cnt;++i)a+=in[i],b+=out[i];
    92         cout<<max(a,b)<<endl;
    93         
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    MySQL 幻读详解
    vue-layer 弹窗z-index问题
    vue-cli 路径不变 改变参数 显示不同组件
    mysql ---- limit使用方式
    mysql ---- 官网的测试数据库
    2020年度总结和2021年目标
    校招(春招实习 + 秋招)总结感想
    Centos8和7的区别(参照redhat)
    centos8 网卡命令(centos7也可用)
    排查linux系统是否被入侵
  • 原文地址:https://www.cnblogs.com/zzqc/p/10072147.html
Copyright © 2011-2022 走看看