码迷,mamicode.com
首页 > 其他好文 > 详细

POJ2186

时间:2016-05-12 17:26:30      阅读:121      评论:0      收藏:0      [点我收藏+]

标签:

Problem: Popular Cows
Description: 有N头牛,M对关系,表示A欢迎B,欢迎关系具有传递性。现在让你求所有头牛都欢迎的牛的头数。
Solution: 如果所有牛的关系形成一个环,那么这个圈中的所有的牛都是满足条件的,这个条件就对应了强连通分量的概念,一个强连通分图中的牛肯定都是满足条件的;还有一种情况也是满足条件的,就是所有的关系形成一棵树,且所有点都能通到root,这棵树的root就是满足条件的牛。那么我们结合两个条件,解题的方法也就很明显了,先求得强连通分量,然后缩点。再用条件二判断这些点是否能构成一棵树,如果能,那么root中的点就是答案。求强连通分量我用的是kosaraju。tarjan今天学。
Code(C++):

#include <stdio.h>
#include <string.h>

typedef struct tagNode{
    int from,to;
    int next;
    tagNode(){}
    tagNode(int _from,int _to,int _next):
        from(_from),to(_to),next(_next){}
}Node;

const int M=50000+5;

const int E=10000+5;

int head_a[E],head_b[E];

Node adj[M],tadj[M];

int order[E],belong[E];
int sig_link_num[E];
bool used[E];

int sig_link_out[E];

int n,m;

void add_edge(Node e[],int head[],int from,int to,int now)
{
    e[now]=Node(from,to,head[from]);
    head[from]=now;
}

void dfs_one(int now,int &time)
{
    used[now]=true;
    for(int i=head_a[now];i+1;i=adj[i].next)
        if(!used[adj[i].to])
            dfs_one(adj[i].to,time);
    order[time++]=now;
}

void dfs_two(int now,int beto)
{
    used[now]=true;
    belong[now]=beto;
    ++sig_link_num[beto];
    for(int i=head_b[now];i+1;i=tadj[i].next)
        if(!used[tadj[i].to])
            dfs_two(tadj[i].to,beto);
}

int kosaraju()
{
    memset(used,false,sizeof(used));
    int time=0;
    for(int i=1;i<=n;i++)
        if(!used[i])
            dfs_one(i,time);

    memset(used,false,sizeof(used));
    memset(sig_link_num,0,sizeof(sig_link_num));
    int ans=0;
    for(int i=time-1;i>=0;i--)
        if(!used[order[i]])
            dfs_two(order[i],ans++);

    memset(sig_link_out,0,sizeof(sig_link_out));

    for(int i=1;i<=n;i++)
        for(int j=head_a[i];j+1;j=adj[j].next)
            if(belong[i]!=belong[adj[j].to])
                ++sig_link_out[belong[i]];

    int return_num=0;
    int tmp=0;
    for(int i=0;i<ans;i++)
        if(!sig_link_out[i])
            ++tmp,return_num=sig_link_num[i];
    return tmp==1? return_num:0;
}

int main()
{
    while(~scanf("%d%d",&n,&m)){

        memset(head_a,-1,sizeof(head_a));
        memset(head_b,-1,sizeof(head_b));

        int from,to;
        for(int i=0;i<m;i++){
            scanf("%d%d",&from,&to);
            add_edge(adj,head_a,from,to,i);
            add_edge(tadj,head_b,to,from,i);
        }

        int ans=kosaraju();
        printf("%d\n",ans);
    }
    return 0;
}

POJ2186

标签:

原文地址:http://blog.csdn.net/flushhip/article/details/51356586

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!