zoukankan      html  css  js  c++  java
  • poj 2186 强连通分量

    poj 2186 强连通分量

    传送门

    Popular Cows
    Time Limit: 2000MS		Memory Limit: 65536K
    Total Submissions: 33414		Accepted: 13612
    Description
    
    Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M <= 50,000) ordered pairs of the form (A, B) that tell you that cow A thinks that cow B is popular. Since popularity is transitive, if A thinks B is popular and B thinks C is popular, then A will also think that C is 
    popular, even if this is not explicitly specified by an ordered pair in the input. Your task is to compute the number of cows that are considered popular by every other cow. 
    Input
    
    * Line 1: Two space-separated integers, N and M 
    
    * Lines 2..1+M: Two space-separated numbers A and B, meaning that A thinks B is popular. 
    Output
    
    * Line 1: A single integer that is the number of cows who are considered popular by every other cow. 
    Sample Input
    
    3 3
    1 2
    2 1
    2 3
    Sample Output
    
    1
    Hint
    
    Cow 3 is the only cow of high popularity. 
    

    我们可以将一个强联通分量看成一个点进行处理,因为这个强连通分量中的点都是相互可达的,那么只要其中一头牛成为红人,那么其他牛也是一样的,同时我们可以得到两个结论

    1. 最终答案必然只是一个强连通分量(如果有两个,那么根据所有点必须可达这个点的条件,那么这两个点集必然属于一个强连通分量,与假设不合,证明成立)
    2. 最终答案就是拓扑排序最后的那个强连通分量,这是根据拓扑排序的性质得来的
      所以我们只需要求出那个强连通分量,最终再反向dfs验证是否可达每个点,这题就解出来了。
    #include <queue>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #define ll long long
    #define inf 1000000000LL
    #define mod 1000000007
    using namespace std;
    int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=x*10+ch-'0';
            ch=getchar();
        }
        return x*f;
    }
    const int N=1e4+10;
    const int M=5e4+10;
    int A[M],B[M],n,m;
    vector<int> G[N];       //图
    vector<int>rG[N];       //反向图
    vector<int>vs;          //后序遍历的顶点列表
    bool vis[N];
    int  cmp[N];             //所属强连通分量的拓扑序
    int sum[N];
    void Addedge(int from,int to){
        G[from].push_back(to);
        rG[to].push_back(from);
    }
    void dfs(int v){
        vis[v]=true;
        for(int i=0;i<G[v].size();i++){
            if(!vis[G[v][i]]) dfs(G[v][i]);
        }
        vs.push_back(v);
    }
    void rdfs(int v,int k){
        vis[v]=true;
        cmp[v]=k;
        sum[k]++;
        for(int i=0;i<rG[v].size();i++){
             if(!vis[rG[v][i]]) rdfs(rG[v][i],k);
        }
    }
    int scc(){
        memset(vis,0,sizeof(vis));
        vs.clear();
        for(int v=0;v<n;v++){
              if(!vis[v]) dfs(v);
        }
        memset(vis,0,sizeof(vis));
        int k=0;
        for(int i=vs.size()-1;i>=0;i--){
               if(!vis[vs[i]]) rdfs(vs[i],k++); //遍历每个联通分量的点集
        }
        return k;
    }
    int main(){
       // while(true)
        {
            n=read();m=read();
            for(int i=0; i<m; i++){
                A[i]=read();B[i]=read();
                 Addedge(A[i]-1,B[i]-1);
            }
            int count=scc();
            int u=0,num=sum[count-1];
            for(int v=0;v<n;v++){
                if(cmp[v]==count-1){
                    u=v;
                    break;
                }
            }
            memset(vis,0,sizeof(vis));
            rdfs(u,0);
            for(int v=0;v<n;v++){
                if(!vis[v]){
                    num=0;
                    break;
                }
            }
            printf("%d
    ",num);
        }
        return 0;
    }
    
    /*
    5 5
    1 2
    1 3
    2 4
    4 5
    5 2
    */
    
    
    
  • 相关阅读:
    Day18:继续添加前端代码
    Day17:今天为前端做的几件小事
    Day16:接口调试完成&紧急转前端开发
    Day25:报告编写等
    Day24:结论的撰写&&openid再次尝试
    Day23:个人小结的撰写&&对coderunner的熟悉
    Day22:数据库导入&分工&准备科研训练
    Day21:尝试脱离相同ip连接
    Day20:update功能的实现
    Day19:代码整合等
  • 原文地址:https://www.cnblogs.com/zsyacm666666/p/6807398.html
Copyright © 2011-2022 走看看