zoukankan      html  css  js  c++  java
  • poj2186 强连通缩点

    Popular Cows
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 29141   Accepted: 11779

    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

    题意:要求找到所有点都能遍历到的点的个数
    思路:强连通分量缩点(环缩点),化成DAG图,也就是树或者深林,讨论有没有出度为0的点,记录这些点的sum,如果sum=1,说明该点所有其他点都能遍历得到,sum>1,说明此图不存在这样的点,【(1->2,1-> 3)这种情况或者图为森林】
    找到该点后,记录该点缩点前的个数
    强连通缩点的算法依然用targan,栈处理有点和前面的判断缩点,双连通分量不同,判断条件为low[u]==dfn[u]
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <algorithm>
    #include <string>
    #include <vector>
    #include <stack>
    #include <queue>
    
    const int inf = 0x3f3f3f;
    const int MAXN = 1e4+10;
    const int MMAXN = 5e4+10;
    struct edge{
      int st;
      int to;
      int next;
      int vis;
    };
    
    using namespace std;
    edge e[MMAXN];
    stack<int>s;
    int first[MAXN];
    int dfn[MAXN];
    int low[MAXN];
    int mark[MAXN];
    int out[MAXN];
    int top,sum,cur,ans;
    int flag;
    int n,m;
    
    void init(){
        memset(first,-1,sizeof(first));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(mark,-1,sizeof(mark));
        memset(out,0,sizeof(out));
        top = sum = cur = flag = ans = 0;
    }
    
    void addedge(int u,int v){
        e[top].st = u;
        e[top].to = v;
        e[top].vis = 0;
        e[top].next = first[u];
        first[u] = top++;
    }
    
    void dfs(int u,int t){
        dfn[u] = low[u] = t;
        int v;
        s.push(u);
        for(int i=first[u];i!=-1;i=e[i].next){
            v = e[i].to;
            if(!dfn[v]){
                dfs(v,t+1);
                low[u] = min(low[u],low[v]);
            }
            else{
                low[u] = min(low[u],dfn[v]);
            }
        }
    
        if(low[u]==dfn[u]){
            /*cout<<"********"<<endl;
            cout<<u<<endl;
            cout<<"********"<<endl;*/
            while(s.top()!=u){
                mark[s.top()] = cur;
                s.pop();
            }
            mark[s.top()] = cur;
            s.pop();
            cur++;
        }
    }
    
    int main()
    {
       // init();
        int a,b,x;
        while(scanf("%d%d",&n,&m)!=EOF){
            init();
            for(int i=0;i<m;i++){
                scanf("%d%d",&a,&b);
                addedge(a,b);
            }
            for(int i=1;i<=n;i++){
                if(!dfn[i])
                    dfs(i,1);
            }
            /*for(int i=1;i<=n;i++){
                cout<<mark[i]<<" ";
            }
            cout<<endl;*/
            for(int i=1;i<=n;i++){
                for(int j=first[i];j!=-1;j=e[j].next){
                    int v = e[j].to;
                    if(mark[i]!=mark[v]){
                        out[mark[i]]++;
                    }
                }
            }
            /*for(int i=0;i<cur;i++){
                cout<<out[i]<<" ";
            }
            cout<<endl;*/
            for(int i=0;i<cur;i++){
                if(out[i]==0){
                    sum++;
                    x = i;
                }
            }
            if(sum!=1){
                cout<<0<<endl;
                continue;
            }
            for(int i=1;i<=n;i++){
                if(mark[i]==x)ans++;
            }
            cout<<ans<<endl;
        }
        //cout << "Hello world!" << endl;
        return 0;
    }
    View Code
    在一个谎言的国度,沉默就是英雄
  • 相关阅读:
    Visual C# 2005中编写Socket网络程序
    [ASP.NET缓存BUG]这几天遇到的头痛问题之一,晚上遇到终于解决一劳永逸
    检测远程URL是否存在的三种方法<转>
    C#开源资源大汇总
    Asp.Net中动态页面转静态页面
    开发人员必进的网站
    基于反向代理的Web缓存加速——可缓存的CMS系统设计
    解决MVC3 服务器无法在已发送 HTTP 标头之后设置状态 问题
    HyperLink 控件控制图片宽度高度的几种方法
    C#进程注入
  • 原文地址:https://www.cnblogs.com/EdsonLin/p/5456258.html
Copyright © 2011-2022 走看看