The Bottom of a Graph
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 9003 | Accepted: 3728 |
Description
We will use the following (standard) definitions from graph theory. Let
V be a nonempty and finite set, its elements being called vertices (or nodes). Let
E be a subset of the Cartesian product
V×V, its elements being called edges. Then
G=(V,E) is called a directed graph.
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.
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
The input contains several test cases, each of which corresponds to a directed graph
G. Each test case starts with an integer number
v, denoting the number of vertices of
G=(V,E), where the vertices will be identified by the integer numbers in the set
V={1,...,v}. You may assume that
1<=v<=5000. That is followed by a non-negative integer
e and, thereafter,
e pairs of vertex identifiers
v1,w1,...,ve,we with the meaning that
(vi,wi)∈E. There are no edges other than specified by these pairs. The last test case is followed by a zero.
Output
For each test case output the bottom of the specified graph on a single line. To this end, print the numbers of all nodes that are sinks in sorted order separated by a single space character. If the bottom is empty, print an empty line.
![](https://i-blog.csdnimg.cn/blog_migrate/707381fc711eb3b9ff89204aca2843e7.jpeg)
Sample Input
3 3 1 3 2 3 3 1 2 1 1 2 0
Sample Output
1 3 2
题意:给一个有向图,求出所有link点,若存在一条路径u->v,一定存在路径v->u,那么u则为link点。
题解:将强连通分量缩点,形成的新图一定是DAG,所以图中出度为0的强连通分量中的点一定为link点。代码如下:
#include<stdio.h>
#include<iostream>
#include<queue>
#include<algorithm>
#include<stack>
#include<math.h>
#include<vector>
#include<string.h>
#define nn 5500
#define inff 0x3fffffff
using namespace std;
int n,m;
struct node
{
int en,next;
}E[nn*nn];
int p[nn],num;
void init()
{
memset(p,-1,sizeof(p));
num=0;
}
void add(int st,int en)
{
E[num].en=en;
E[num].next=p[st];
p[st]=num++;
}
int dfn[nn],low[nn],df;
int cnt;
int fa[nn];
bool insta[nn];
stack<int>sta;
void dfs(int id)
{
dfn[id]=low[id]=++df;
sta.push(id);
insta[id]=true;
int i,w;
for(i=p[id];i+1;i=E[i].next)
{
w=E[i].en;
if(dfn[w]==-1)
{
dfs(w);
low[id]=min(low[id],low[w]);
}
else if(insta[w])
low[id]=min(low[id],dfn[w]);
}
if(low[id]==dfn[id])
{
++cnt;
int ix;
while(1)
{
ix=sta.top();
sta.pop();
insta[ix]=false;
fa[ix]=cnt;
if(ix==id)
break;
}
}
}
int cd[nn];
vector<int>ans;
void solve()
{
memset(cd,0,sizeof(cd));
memset(insta,false,sizeof(insta));
memset(dfn,-1,sizeof(dfn));
df=cnt=0;
int i,j,w;
for(i=1;i<=n;i++)
{
if(dfn[i]==-1)
{
dfs(i);
}
}
for(i=1;i<=n;i++)
{
for(j=p[i];j+1;j=E[j].next)
{
w=E[j].en;
if(fa[i]!=fa[w])
{
cd[fa[i]]++;
}
}
}
for(i=1;i<=cnt;i++)
{
if(cd[i]==0)
{
for(j=1;j<=n;j++)
{
if(fa[j]==i)
{
ans.push_back(j);
}
}
}
}
}
int main()
{
int i;
while(scanf("%d",&n)&&n)
{
scanf("%d",&m);
int u,v;
init();
for(i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
}
ans.clear();
solve();
sort(ans.begin(),ans.end());
for(i=0;i<(int)ans.size();i++)
{
printf("%d%c",ans[i],i==(ans.size()-1)?'\n':' ');
}
if(ans.empty())
puts("");
}
return 0;
}