想看更多的解題報告:http://blog.csdn.net/wangjian8006/article/details/7870410
轉載請註明出處:http://blog.csdn.net/wangjian8006
題目大意:如果v點能夠到的點,反過來能夠到達v點,則稱這個點為sink點,輸出所有的sink點
解題思路:求連通分量,然後出度為0的連通分量裡面的點就是sink點
/*kosarajuMemory 524KTime 63MS*/#include <iostream>using namespace std;#define MAXM 50010#define MAXV 5010#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,j,outdegree[MAXV]={0};for(i=1;i<=n;i++)for(j=headlist[i];j!=-1;j=edge[j].next)if(belong[i]!=belong[edge[j].t]){outdegree[belong[i]]++;}memset(vis,0,sizeof(vis));for(i=1;i<=n;i++)if(!outdegree[belong[i]]) vis[i]=1;for(i=1;i<=n;i++)if(vis[i]) printf("%d ",i);printf("\n");}int main(){int i,a,b;while(scanf("%d",&n) && n){memset(headlist,-1,sizeof(headlist));memset(headlist2,-1,sizeof(headlist2));scanf("%d",&m);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;}
====================================================================
/*tarjanMemory 544KTime 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;}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,j,outdegree[MAXV]={0};for(i=1;i<=n;i++)for(j=headlist[i];j!=-1;j=edge[j].next)if(belong[i]!=belong[edge[j].t]){outdegree[belong[i]]++;}memset(instack,0,sizeof(instack));for(i=1;i<=n;i++)if(!outdegree[belong[i]]) instack[i]=1;for(i=1;i<=n;i++)if(instack[i]) printf("%d ",i);printf("\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;}