zoukankan      html  css  js  c++  java
  • 连通图 poj2186 最受欢迎的牛(求最受欢迎的牛的数量)

      Popular Cows
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 27531   Accepted: 11077

    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.

    Source

     
    本题题意时每个牛都可以仰慕求它的牛,而且仰慕关系可以互相传递
    问最受欢迎的牛的数量有多少个
    可以利用强联通的缩点法,最后求缩点之后的初度为0的点的数量,
    注意一个问题就是:
    如果没有出度为0的点,那么结果输出答案为0
    下面提供了几组样例,主要注意的输出为0的点需要特别判断
    解决该题目的模板同上面的那个解决学校之间传递数量文件关系的拿到题所用的模板都是一套模板,而且判断入度出度那里也咩有变化
    ps::附上嗲吗
    #include <string.h>
    #include <stdio.h>
    #define V    10500
    #define E    50500
    
    struct edge
    {
        int to, next;
    }Edge[E];
    int head[V], e, n;
    
    int indeg[V], outdeg[V]; //点的入度和出度数
    int belong[V], low[V], dfn[V], scc, cnt;//dfn[]:遍历到u点的时间; low[]:u点可到达的各点中最小的dfn[v]
    int S[V], top;
    bool vis[V];//v是否在栈中
    
    int addedge(int u, int v)
    {
        Edge[e].to = v;
        Edge[e].next = head[u];
        head[u] = e++;
        return 0;
    }
    void tarjan(int u)
    {
        int v;
        dfn[u] = low[u] = ++cnt;//开始时dfn[u] == low[u]
        S[top++] = u;//不管三七二十一进栈
        vis[u] = true;
        for (int i=head[u]; i!=-1; i=Edge[i].next)
        {
            v = Edge[i].to;
            if (dfn[v] == 0)//如果v点还未遍历
            {
                tarjan(v);//向下遍历
                low[u] = low[u] < low[v] ? low[u] : low[v];//确保low[u]最小
            }
            else if (vis[v] && low[u] > dfn[v])//v在栈中,修改low[u]
                low[u] = dfn[v];
        }
        if (dfn[u] == low[u])//u为该强连通分量中遍历所成树的根
        {
            ++scc;
            do
            {
                v = S[--top];//栈中所有到u的点都属于该强连通分量,退栈
                vis[v] = false;
                belong[v] = scc;
            } while (u != v);
        }
    
    }
    
    int solve(){
        scc = top = cnt = 0;
        memset(dfn, 0, sizeof(dfn));
        memset(vis, false, sizeof(vis));
        for (int u=1; u<=n; ++u)
            if (dfn[u] == 0)
                tarjan(u);
        return scc;
    }
    
    void count_deg()
    {
        memset(indeg, 0, sizeof(indeg));
        memset(outdeg, 0, sizeof(outdeg));
        for (int u=1; u<=n; ++u)
            for (int i=head[u]; i!=-1; i=Edge[i].next)
            {
                int v = Edge[i].to;
                if (belong[u] != belong[v])
                {
                    indeg[belong[v]]++;
                    outdeg[belong[u]]++;
                }
            }
    }
    
    int main()
    {
        int u, v, i;
        int m;
        while (~scanf("%d%d", &n,&m))
        {
            e = 0;
            memset(head, -1, sizeof(head));
            for (int i=1;i<=m;i++){
                scanf("%d%d",&u,&v);    
                    addedge(u, v);
            }
            solve();
                count_deg();
    
              int num=0,tmp;
            for(int i = 1; i <= scc; i++)  
            {  
                if(!outdeg[i])  
                {  
                    num++;  
                    tmp = i;  
                }  
                      
            }  
              int ans=0;
            if(num == 1)  
            {  
                for(int i = 1; i <= n; i++)  
                {  
                    if(belong[i] == tmp)  
                        ans++;  
                }  
                printf("%d
    ", ans);  
            }  
            else  
            {  
                printf("0
    ");  
            }  
    
            
        }
        return 0;
    }
  • 相关阅读:
    进程、线程、处理器间的关系研究(未完待续)
    Java运行原理研究(未完待续)
    libuv的多线程之间传递消息
    C++对象与其第一个非静态成员地址相同
    libuv移植到android
    pthread在Qt+Windows下的使用
    libuv在mingw下编译
    libxml2在mingw下编译
    libcurl在mingw下编译
    string的内存本质
  • 原文地址:https://www.cnblogs.com/13224ACMer/p/4781453.html
Copyright © 2011-2022 走看看