POJ2553:The Bottom of a Graph(tarjan缩点)
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 7005 | Accepted: 2871 |
Description
Let n be a positive integer, and let p=(e1,...,en) be a sequence of length n of edges ei∈E such that ei=(vi,vi+1) for a sequence of vertices (v1,...,vn+1). Then p is called a path from vertex v1 to vertex vn+1 in G and we say that vn+1 is reachable from v1, writing (v1→vn+1).
Here are some new definitions. A node v in a graph G=(V,E) is called a sink, if for every node w in G that is reachable from v, v is also reachable from w. The bottom of a graph is the subset of all nodes that are sinks, i.e.,bottom(G)={v∈V|∀w∈V:(v→w)⇒(w→v)}. You have to calculate the bottom of certain graphs.
Input
Output
![](http://poj.org/images/2553_1.jpg)
Sample Input
3 3 1 3 2 3 3 1 2 1 1 2 0
Sample Output
1 3 2
Source
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAX 5010
struct node
{
int v;
int next;
}E[MAX*MAX];
int head[MAX];
int num;
int dfn[MAX];
int st[MAX];
bool instack[MAX];
int low[MAX];
int id[MAX];
int top;
int ct;
int tot;
int n,m;
int in[MAX];
int out[MAX];
int ans[MAX];
void init()
{
memset(dfn,0,sizeof(dfn));
memset(head,-1,sizeof(head));
memset(instack,0,sizeof(instack));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
num=0;
ct=0;
top=0;
tot=0;
}
void add(int s,int t)
{
E[num].v=t;
E[num].next=head[s];
head[s]=num++;
}
void dfs(int cur)
{
//cout<<"vis "<<cur<<endl;
dfn[cur]=low[cur]=++ct;
st[top++]=cur;
instack[cur]=1;
int i;
for(i=head[cur];i!=-1;i=E[i].next)
{
int v=E[i].v;
if(!dfn[v])
{
dfs(v);
if(low[v]<low[cur])
low[cur]=low[v];
}
else if(instack[v] && dfn[v]<low[cur])
low[cur]=dfn[v];
}
if(dfn[cur]==low[cur])
{
tot++;
//cout<<"tot="<<tot<<endl;
for(;st[top]!=cur;)
{
int j=st[--top];
id[j]=tot;
instack[j]=false;
}
}
}
void tarjan()
{
int i;
for(i=1;i<=n;i++)
{
if(!dfn[i])
{
dfs(i);
}
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
if(n==0)
break;
scanf("%d",&m);
int i,j;
int s,t;
init();
for(i=1;i<=m;i++)
{
scanf("%d%d",&s,&t);
add(s,t);
//add(t,s);
}
tarjan();
for(i=1;i<=n;i++)
{
int id1=id[i];
for(j=head[i];j!=-1;j=E[j].next)
{
int id2=id[E[j].v];
if(id1==id2)
continue;
out[id1]++;
in[id2]++;
}
}
int cnt=0;
for(i=1;i<=n;i++)
{
if(out[id[i]]==0)
{
ans[cnt++]=i;
}
}
for(i=0;i<cnt;i++)
{
printf("%d",ans[i]);
if(i!=cnt-1)
printf(" ");
}
printf("\n");
}
}
//
tarjan()缩点,所有出度为零的强连通分支里的顶点构成the bottom of graph