tzoj1769: The Bottom of a Graph
原题链接:http://www.tzcoder.cn/acmhome/problemdetail.do?method=showdetail&id=1769
描述
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.
输入
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.
输出
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.

题解:tarjan缩点,在找出出度为0的点。
#include<bits/stdc++.h> using namespace std; const int MAXN = 20010;//点数 const int MAXM = 50010;//边数 struct Edge{ int to,next; }edge[MAXM]; int head[MAXN],tot; int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong 数组的值是 int Index,top; int scc;//强连通分量的个数 bool Instack[MAXN]; int num[MAXN];//各个强连通分量包含点的个数,数组编号 1 ~ scc int du[MAXN]; void addedge(int u,int v){ edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++; } void Tarjan(int u){ int v; Low[u] = DFN[u] = ++Index; Stack[top++] = u; Instack[u] = true; for(int i = head[u];i !=-1;i = edge[i].next){ v = edge[i].to; if( !DFN[v] ){ Tarjan(v); if( Low[u] > Low[v] )Low[u] = Low[v]; } else if(Instack[v] && Low[u] > DFN[v]) Low[u] = DFN[v]; } if(Low[u] == DFN[u]){ scc++; do{ v = Stack[--top]; Instack[v] = false; Belong[v] = scc; num[scc]++; }while( v != u); } } void solve(int N){ memset(DFN,0,sizeof(DFN)); memset(Instack,false,sizeof(Instack)); memset(num,0,sizeof(num)); Index = scc = top = 0; for(int i = 1;i <= N;i++) if(!DFN[i]) Tarjan(i); } void init(){ tot = 0; memset(head,-1,sizeof(head)); memset(edge,0,sizeof(edge)); memset(du,0,sizeof(du)); } int main() { int n,m; while(scanf("%d",&n)) { if(n==0)break; init(); scanf("%d",&m); int u,v; for(int i=0;i<m;i++) { scanf("%d%d",&u,&v); addedge(u,v); } solve(n); for(int i=1;i<=n;i++) for(int j = head[i];j!= -1;j = edge[j].next) { v=edge[j].to; if(Belong[i]!=Belong[v]) du[Belong[i]]++; } int flag=0; for(int i=1;i<=n;i++) { if(du[Belong[i]]==0) { if(!flag) { printf("%d",i); flag=1; } else printf(" %d",i); } } printf("\n"); } return 0; }

浙公网安备 33010602011771号