• 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
    */
    
    
    
  • 相关阅读:
    梯度提升树算法GBDT
    优先队列 priority_queue
    谭平 Vision Course Note 1~2 Recommended Textbook and Camera Basics
    侯捷老师C++基础课程笔记7-栈、堆和内存管理
    侯捷老师C++基础课程笔记6-三大特殊函数
    侯捷老师C++基础课程笔记5-操作符重载与临时对象
    侯捷老师C++基础课程笔记4-参数传递与返回值
    侯捷老师C++基础课程笔记3-构造函数(不含指针变量的class)
    侯捷老师C++基础课程笔记1-2
    C文件处理之24/32位bmp图像的旋转
  • 原文地址:https://www.cnblogs.com/zsyacm666666/p/6807398.html
Copyright © 2020-2023  润新知