poj2186 - Popular Cows

来源:互联网 发布:沈阳盘古网络工资 编辑:程序博客网 时间:2024/05/02 15:49

                                想看更多的解题报告:http://blog.csdn.net/wangjian8006/article/details/7870410
                                  转载请注明出处:
http://blog.csdn.net/wangjian8006

题目大意:题目大意是:在一个牧群中,有N个奶牛,给定M对关系(A,B)表示A仰慕B,而且仰慕关系有传递性,问被所有奶牛(除了自己)仰慕的奶牛个数
解题思路:找出所有的连通分量,如果只有一个连通分量的出度为0,那么输出那个连通分量的点的个数即可,如果不唯一就输出0
因为连通分量的出度有两个的话,那么肯定至少存在一头牛不仰慕另外一头牛,所以我们至少保证要出度为0的连通分量唯一

 

/*tarjanMemory 872KTime   32MS*/#include <iostream>using namespace std;#define MAXM 50010#define MAXV 10010#define min(a,b) (a>b?b:a)typedef struct{int s,t,next;}Edge;Edge edge[MAXM];int n,m,headlist[MAXV];int dfn[MAXV];//第一次访问的步数int low[MAXV];//子树中最早的步数int stap[MAXV],stop;//模拟栈bool instack[MAXV];//是否在栈中int count;//记录连通分量的个数int cnt;//记录搜索步数int belong[MAXV];//属于哪个连通分量void init(){count=stop=cnt=0;memset(instack,false,sizeof(instack));memset(dfn,0,sizeof(dfn));}void tarjan(int x){int i;dfn[x]=low[x]=++cnt;stap[stop++]=x;instack[x]=true;for(i=headlist[x];i!=-1;i=edge[i].next){int a=edge[i].t;if(!dfn[a]){tarjan(a);low[x]=min(low[a],low[x]);}else if(instack[a])low[x]=min(dfn[a],low[x]);}if(low[x]==dfn[x]){count++;while(1){int tmp=stap[--stop];belong[tmp]=count;instack[tmp]=false;if(tmp==x) break;}}}void work(){init();for(int i=1;i<=n;i++)if(!dfn[i]) tarjan(i);}void output(){int i,outdegree[MAXV]={0},outzero=0,ans=0;for(i=0;i<m;i++){if(belong[edge[i].s]!=belong[edge[i].t]){outdegree[belong[edge[i].s]]++;}}for(i=1;i<=count;i++){if(!outdegree[i]){outzero++;cnt=i;}}for(i=1;i<=n;i++)if(belong[i]==cnt) ans++;if(outzero==1)printf("%d\n",ans);else printf("0\n");}int main(){int i,a,b;while(~scanf("%d%d",&n,&m)){memset(headlist,-1,sizeof(headlist));for(i=0;i<m;i++){scanf("%d%d",&a,&b);edge[i].s=a;edge[i].t=b;edge[i].next=headlist[a];headlist[a]=i;}work();output();}return 0;}


=============================================================================

 

/*kosarajuMemory 1036KTime    63MS*/#include <iostream>using namespace std;#define MAXM 50010#define MAXV 10010#define min(a,b) (a>b?b:a)typedef struct{int s,t,next,next2;}Edge;Edge edge[MAXM];int n,m,headlist[MAXV],headlist2[MAXV];int order[MAXV],belong[MAXV];int num,count;bool vis[MAXV];void dfs(int x){int i,a;vis[x]=1;for(i=headlist[x];i!=-1;i=edge[i].next){a=edge[i].t;if(!vis[a]) dfs(a);}order[++num]=x;}void dfst(int x){int i,a;belong[x]=count;//记录结点属于哪个连通分量vis[x]=1;for(i=headlist2[x];i!=-1;i=edge[i].next2){//要将边反过来遍历一遍a=edge[i].s;if(!vis[a]) dfst(a);}}void kosaraju(){int i;memset(vis,0,sizeof(vis));num=count=0;for(i=1;i<=n;i++)if(!vis[i]) dfs(i);memset(vis,0,sizeof(vis));for(i=n;i>=1;i--)if(!vis[order[i]]){count++;dfst(order[i]);}}void output(){int i,outdegree[MAXV]={0},outzero=0,ans=0,cnt;for(i=0;i<m;i++){if(belong[edge[i].s]!=belong[edge[i].t]){outdegree[belong[edge[i].s]]++;}}for(i=1;i<=count;i++){if(!outdegree[i]){outzero++;cnt=i;}}for(i=1;i<=n;i++)if(belong[i]==cnt) ans++;if(outzero==1)printf("%d\n",ans);else printf("0\n");}int main(){int i,a,b;while(~scanf("%d%d",&n,&m)){memset(headlist,-1,sizeof(headlist));memset(headlist2,-1,sizeof(headlist2));for(i=0;i<m;i++){scanf("%d%d",&a,&b);edge[i].s=a;edge[i].t=b;edge[i].next=headlist[a];headlist[a]=i;edge[i].next2=headlist2[b];//记录反边headlist2[b]=i;}kosaraju();output();}return 0;}


 

 

原创粉丝点击