POJ 2553 The Bottom of a Graph
题意:在有向图G中,给这样一个新的定义:对于在G中任何一个点v可达的点w,w都可达v,那么点v是一个sink。G图的bottom子图是由G图中所有的sink点构成,请按照顺序输出G图对应的bottom子图中的所有点编号,如果没有sink点,那么输出一个空行。
题目分析:先将题目的强联通分量求出来缩成点,然后判断连通分量出度为0点 分量。
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <algorithm> #include <vector> usingnamespace std; #define INF 0x7ffffff #define maxn 5005 typedef longlong LL; #define Min(a,b) (a<b?a:b) #define MOD 1000000007 int m, n, Time, top, ans; int Stack[maxn], dfn[maxn], low[maxn], blocks[maxn], Out[maxn]; bool InStack[maxn]; vector<vector<int> > G; void init() { memset(Out, 0, sizeof(Out)); memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); ans = Time = top = 0; G.clear(); G.resize(n+2); } void Tarjan(int u) { dfn[u] = low[u] = ++Time; Stack[top++] = u; InStack[u] = true; int len = G[u].size(), v; for(int i=0; i<len; i++) { v = G[u][i]; if( !low[v] ) { Tarjan(v); low[u] = min(low[u], low[v]); } elseif( InStack[v] ) low[u] = min(low[u], dfn[v]); } if(low[u] == dfn[u]) { do { v = Stack[--top]; InStack[v] = false; blocks[v] = ans; } while(u != v); ans ++; } } void solve() { for(int i=1; i<=n; i++) { if(!low[i]) Tarjan(i); } for(int i=1; i<=n; i++) { int len = G[i].size(), v; for(int j=0; j<len; j++) { v = G[i][j]; if(blocks[i] != blocks[v]) Out[blocks[i]] ++; } } int flag = 0; for(int i=1; i<=n; i++) { if(Out[blocks[i]] == 0 && !flag) { flag ++; printf("%d", i); } elseif(Out[blocks[i]] == 0) printf(" %d", i); } printf("\n"); } int main() { while(scanf("%d",&n), n) { scanf("%d",&m); init(); while(m --) { int a, b; scanf("%d %d",&a, &b); G[a].push_back(b); } solve(); } return0; }