• POJ2186 Popular Cows(强连通分量)


    题目问一个有向图所有点都能达到的点有几个。

    先把图的强连通分量缩点,形成一个DAG,那么DAG“尾巴”(出度0的点)所表示的强连通分量就是解,因为前面的部分都能到达尾巴,但如果有多个尾巴那解就是0了,因为尾巴间达到不了。判断是否有多个尾巴,可以从最后一个强连通分量中的某一个点出发看能否在逆图上遍历完其他点。

    因为用到了逆图,所以直接用Kosaraju算法。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 #include<algorithm>
     5 using namespace std;
     6 #define MAXM 111111
     7 #define MAXN 11111
     8 struct Edge{
     9     int v,next;
    10 }edge[MAXM];
    11 int NE,head[MAXN],rhead[MAXN];
    12 void addEdge(int u,int v){
    13     edge[NE].v=v; edge[NE].next=head[u]; head[u]=NE++;
    14     edge[NE].v=u; edge[NE].next=rhead[v]; rhead[v]=NE++;
    15 }
    16 
    17 int belong[MAXN];
    18 bool vis[MAXN];
    19 vector<int> post;
    20 void dfs(int u){
    21     vis[u]=1;
    22     for(int i=head[u]; i!=-1; i=edge[i].next){
    23         int v=edge[i].v;
    24         if(vis[v]) continue;
    25         dfs(v);
    26     }
    27     post.push_back(u);
    28 }
    29 void rdfs(int u,int k){
    30     vis[u]=1; belong[u]=k;
    31     for(int i=rhead[u]; i!=-1; i=edge[i].next){
    32         int v=edge[i].v;
    33         if(vis[v]) continue;
    34         rdfs(v,k);
    35     }
    36 }
    37 int rdfs(int u){
    38     int res=1;
    39     vis[u]=1;
    40     for(int i=rhead[i]; i!=-1; i=edge[i].next){
    41         int v=edge[i].v;
    42         if(vis[v]) continue;
    43         res+=rdfs(v);
    44     }
    45     return res;
    46 }
    47 int scc(int n){
    48     memset(vis,0,sizeof(vis));
    49     post.clear();
    50     for(int i=1; i<=n; ++i){
    51         if(!vis[i]) dfs(i);
    52     }
    53     memset(vis,0,sizeof(vis));
    54     int k=0;
    55     for(int i=post.size()-1; i>=0; --i){
    56         int v=post[i];
    57         if(!vis[v]) rdfs(v,++k);
    58     }
    59     memset(vis,0,sizeof(vis));
    60     for(int i=1; i<=n; ++i){
    61         if(belong[i]==k){
    62             if(rdfs(i)!=n) return 0;
    63             break;
    64         }
    65     }
    66     int res=0;
    67     for(int i=1; i<=n; ++i){
    68         if(belong[i]==k) ++res;
    69     }
    70     return res;
    71 }
    72 int main(){
    73     memset(head,-1,sizeof(head));
    74     memset(rhead,-1,sizeof(rhead));
    75     int n,m,a,b;
    76     scanf("%d%d",&n,&m);
    77     while(m--){
    78         scanf("%d%d",&a,&b);
    79         addEdge(a,b);
    80     }
    81     printf("%d",scc(n));
    82     return 0;
    83 }
  • 相关阅读:
    scala 中的修饰符
    scala 主从构造器
    scala 伴生对象与伴生类
    scala 通过apply创建类的对象
    kali linux 全版本(以前的版本)镜像下载
    install python in wine
    SSH防爆破脚本
    SSH私用私钥登陆
    linux 内核提权
    Windows下MYSQL读取文件为NULL
  • 原文地址:https://www.cnblogs.com/WABoss/p/5155736.html
Copyright © 2020-2023  润新知