首页 > 其他 > 详细

POJ2186(有向图缩点&判图连通)

时间:2016-01-29 03:14:16      阅读:172      评论:0      收藏:0      [点我收藏+]
Popular Cows
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 28379   Accepted: 11488

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
题意:A认为B受欢迎,B认为C受欢迎,那么A就认为C受欢迎。给定N头牛,M个认为受欢迎情况。确定受所有牛欢迎的这些牛的数目。
思路:首先判断有向图是否连通,若不连通则答案为0。若连通则进行缩点(注意有向图与无向图的缩点的不同之处),缩点之后得到一个有向树。若树中存在多个叶子结点,则答案为0,否则答案为 缩成叶子结点的那个连通分量重结点的数目。
#include"cstdio"
#include"cstring"
#include"vector"
using namespace std;
const int MAXN=10005;
int V,E;
vector<int> G[MAXN];
vector<int> rG[MAXN];
int vis[MAXN];
int deg[MAXN];
int pos;
void dfs(int u)
{
    vis[u]=1;
    pos=u;
    for(int i=0;i<G[u].size();i++)
    {
        int to=G[u][i];
        if(!vis[to])
        {
            dfs(to);
        }
    }
}
void rdfs(int u)
{
    vis[u]=1;
    for(int i=0;i<rG[u].size();i++)
    {
        int to=rG[u][i];
        if(!vis[to])
        {
            rdfs(to);
        }
    }
}
bool pass()
{
    memset(vis,0,sizeof(vis));
    dfs(1);
    memset(vis,0,sizeof(vis));
    rdfs(pos);
    for(int i=1;i<=V;i++)
        if(!vis[i])    return false;
    return true;
}
int index;
int dfn[MAXN],low[MAXN];
int stack[MAXN],top;
int cpnt[MAXN],cnt;
inline int min(int a,int b)
{
    return a > b? b: a;
}
void tarjan(int u,int fa)
{
    stack[top++]=u;
    dfn[u]=low[u]=++index;
    for(int i=0;i<G[u].size();i++)
    {
        int to=G[u][i];
        if(!dfn[to])
        {
            tarjan(to,u);
            low[u]=min(low[u],low[to]);
        }
        else low[u]=min(low[u],dfn[to]);//注意有向图与无向图缩点的不同 
    }
    if(dfn[u]==low[u])
    {
        int v;
        ++cnt;
        do{
            v=stack[--top];
            cpnt[v]=cnt;
        }while(u!=v);
    }
}
int seek()
{
    for(int i=1;i<=V;i++)
        for(int j=0;j<G[i].size();j++)
        {
            int to=G[i][j];
            if(cpnt[i]!=cpnt[to])
            {
                deg[cpnt[i]]++;
            }
        }
    int v;
    int flag=0;
    for(int i=1;i<=cnt;i++)
        if(deg[i]==0)//答案肯定为叶子结点 
        {
            v=i;
            flag++;
        }
    if(flag>1)    return 0;//必须只存在一个叶子结点 
    int ans=0;
    for(int i=1;i<=V;i++)
        if(cpnt[i]==v)    ans++;
    return ans;
}
int main()
{
    while(scanf("%d%d",&V,&E)!=EOF)
    {
        for(int i=1;i<=V;i++)
        {
            G[i].clear();
            rG[i].clear();
        }
        for(int i=0;i<E;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            rG[v].push_back(u);
        }
        if(pass())
        {
            index=0;
            memset(dfn,0,sizeof(dfn));
            memset(low,0,sizeof(low));
            top=0;
            cnt=0;
            memset(cpnt,0,sizeof(cpnt));
            tarjan(1,-1);
            memset(deg,0,sizeof(deg));
            int ans=seek();
            printf("%d\n",ans);
        }
        else
        {
            printf("0\n");
        }
    }
    
    return 0;
}

 



POJ2186(有向图缩点&判图连通)

原文:http://www.cnblogs.com/program-ccc/p/5167845.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!