旅游电车(cogs 1175)
【问题描述】
Henryy国正致力于首都的一个旅游电车建设工程。首都有N个旅游景区。Henryy国的电车永远只沿道路规定的方向行驶,为了不使投入使用的电车有可能无法回到它的起始站,Henryy希望知道他的首都的可以在哪些景区设置站点。一个景区可以被设置成车站,当且仅当对于任意一个从该景区出发所能到达的景区,均至少有一条路可回到该景区。你的同事已完成了一份景区之间的道路连通情况的报告。报告中将给出首都的景区数目N、道路总数M以及一些形如“景区A和景区B之间有一条从A到B的单向道路”的信息。现在明确你的任务:根据报告中的信息,列出所有可以被设置成车站的景区。
【输入文件】
输入文件由多份报告组成(这些报告相互无任何联系),每份报告包括:N,M,接下来M对整数Ai、Bi (1<=I<=M)表示Ai和Bi之间有一条单向道路Ai->Bi。仅一个包含整数N=0的报告表示你的工作结束,你的程序不应该对此有任何反应。各整数间用空格或空行分隔。对于任意景区,分别以该景区为起点或终点的道路总数均不超过50。
【输出文件】
对于每份报告,输出一行列表包括:所有能被设置成电车站点的景区编号,各编号之间用一个空格隔开。
【样例输入】
5 6 1 2 2 3 3 4 4 1 2 5 5 2 1 0 0
【样例输出】
1 2 3 4 5 1
【数据约定】
对于40%的数据,有N<=200。
对于100%的数据,有N<=5000,M<=50000。
/* tarjan算法 题目要求求出的点满足它能连到的点也能连回来,那么就一定要与它在同一缩点中,如果一个缩点出度大于1,那么这个缩点中的所有点都不满足要求。 */ #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define M 5010 using namespace std; int num[M],low[M],instack[M],vis[M],belong[M],out[M],a[M][M],s [M*2],cnt,indexx,top; int head[M],n,m,ans[M]; struct node { int v,pre; };node e[M*10]; int read() { char c=getchar();int num=0,flag=1; while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();} while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();} return num*flag; } void add(int i,int x,int y) { e[i].v=y; e[i].pre=head[x]; head[x]=i; } void tarjan(int v) { num[v]=low[v]=++indexx; vis[v]=instack[v]=1; s[++top]=v; for(int i=head[v];i;i=e[i].pre) { int w=e[i].v; if(!vis[w]) { tarjan(w); low[v]=min(low[v],low[w]); } else if(instack[w]) low[v]=min(low[v],num[w]); } int u; if(num[v]==low[v]) { ++cnt; do { u=s[top--]; instack[u]=0; belong[u]=cnt; a[cnt][++a[cnt][0]]=u; }while(u!=v); } } void work() { for(int i=1;i<=m;i++) { int x=read(),y=read(); add(i,x,y); } for(int i=1;i<=n;i++) if(!vis[i])tarjan(i); for(int i=1;i<=n;i++) for(int j=head[i];j;j=e[j].pre) if(belong[i]!=belong[e[j].v]) out[belong[i]]++; int k=0; for(int i=1;i<=cnt;i++)if(!out[i]) for(int j=1;j<=a[i][0];j++) ans[++k]=a[i][j]; sort(ans+1,ans+k+1); for(int i=1;i<=k;i++) printf("%d ",ans[i]); printf("\n"); } int main() { freopen("buss.in","r",stdin); freopen("buss.out","w",stdout); while(1) { n=read();if(!n)break; m=read(); memset(head,0,sizeof(head)); memset(num,0,sizeof(num)); memset(low,0,sizeof(low)); memset(vis,0,sizeof(vis)); memset(instack,0,sizeof(instack)); memset(s,0,sizeof(s)); memset(e,0,sizeof(e)); memset(belong,0,sizeof(belong)); memset(out,0,sizeof(out)); memset(a,0,sizeof(a)); indexx=cnt=top=0; work(); } return 0; }