zoukankan      html  css  js  c++  java
  • POJ 2186 白书经典 强连通图分量(内附模板)

    题目:https://vjudge.net/problem/POJ-2186

    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.
     
     
    题意:  每头牛都想当红人   给定n头牛的牛群    和m个有序对   (A,B)(B,C)==》(A,C)
         表示A认为B是红人   B认为C是红人  那么就有  A认为C是红人
       求被其它所有牛认为是红人的牛的个数
     
     
    思路:   假如直接遍历每一个顶点搜索的到  复杂度O(n*m)会超时
     
     
               假如  有(A,B) 和(B,A)那么可以把A和B缩成一个点    
     
     
    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<algorithm>
    #include<map>
    #define maxn 200005
    using namespace std;
    bool used[maxn];         //点是否被遍历
    int n,m;                 //顶点数和边数
    vector<int>mp[50005];    //建图数组
    vector<int>mp2[50005];   //反向边建立图
    vector<int>vs;           //后序遍历顺序的顶点列表
    int cmp[maxn];           //强连通分量的拓扑序

    //建立图
    void add_edge(int from,int to)
    {
        mp[from].push_back(to);    //正反建立图
        mp2[to].push_back(from);
    }

    //第一次dfs遍历
    void dfs(int x)
    {
        used[x]=true;  // 标记
        for(int i=0;i<mp[x].size();i++)
        {
            if(!used[mp[x][i]])dfs(mp[x][i]);   //dfs图
        }
        //cout<<x<<endl;
        vs.push_back(x);    //记录遍历的顺序
    }

    //第二次dfs遍历
    void rdfs(int x,int k)
    {
        used[x]=true;  //标记点
        cmp[x] = k;   //记录属于一个集合
        for(int i = 0; i<mp2[x].size(); i ++)
        {
            if(!used[mp2[x][i]])rdfs(mp2[x][i],k);
        }
    }

    //查询模板  计算强连通图的个数
    int scc()
    {
        memset(used,false,sizeof(used));
        vs.clear();
        for(int i = 0;i < n;i ++)
        {
            if(!used[i])dfs(i);
        }
        memset(used,false,sizeof(used));
        int k=0;
        for(int i=vs.size()-1;i>=0;i--)    //从查询顺序和第一次查询顺序相反
        {
            if(!used[vs[i]])rdfs(vs[i],k++);
        }
            return k;
    }

    int a[maxn],b[maxn];
    int main()
    {
        cin>>n>>m;
        for(int i=0;i<m;i++)
        {
            cin>>a[i]>>b[i];
            add_edge(a[i]-1,b[i]-1);
        }
        int ans=scc();
        int flag=0;
        int num=0;
        //cout<<ans<<endl;
        for(int i=0;i<n;i++)
        {
            if(cmp[i]==ans-1)
            {
                flag=i;
                num++;
            }
        }
       // cout<<flag<<endl;
       //cout<<num<<endl;
        //检查是否从所有点可达
        memset(used,false,sizeof(used));
        rdfs(flag,0);     //重新用强连通分量分解的代码
        for(int i=0;i<n;i++)
        {
            if(!used[i]){
                num=0;
            break;
            }
        }
        cout<<num<<endl;
         return 0;
    }

    /*

    12 16
    2 3
    3 2
    4 3
    4 1
    5 7
    6 3
    6 4
    6 5
    7 6
    8 10
    9 8
    9 7
    10 9
    11 8
    11 10
    12 11

    0

    */

     
     
     
     
     
               
  • 相关阅读:
    【Linux学习三】Linux系统目录架构
    【Linux学习二】Linux文件系统
    【Python网络爬虫四】通过关键字爬取多张百度图片的图片
    【GitHub】命令行操作
    【Linux学习一】命令行CLI、BASH的基本操作
    从CK+库提取标记点信息
    【Python网络爬虫三】 爬取网页新闻
    Windows命令行下pip安装python whl包
    【GitHub Desktop】MacOS和Win下配置及简单的使用
    【Python文件处理】递归批处理文件夹子目录内所有txt数据
  • 原文地址:https://www.cnblogs.com/huangzzz/p/8858807.html
Copyright © 2011-2022 走看看