想看更多的解题报告:http://iyenn.com/rec/1824570.html
转载请注明出处:http://blog.csdn.net/wangjian8006
题目大意:如果v点能够到的点,反过来能够到达v点,则称这个点为sink点,输出所有的sink点
解题思路:求连通分量,然后出度为0的连通分量里面的点就是sink点
- /*
- kosaraju
- Memory 524K
- Time 63MS
- */
- #include
- 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
- 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;
- }
====================================================================
- /*
- tarjan
- Memory 544K
- Time 63MS
- */
- #include
- 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
- 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;
- }
注:本文转载自blog.csdn.net的wangjian8006的文章"http://blog.csdn.net/wangjian8006/article/details/7894768"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
评论记录:
回复评论: