poj 2553 The Bottom of a Graph
http://poj.org/problem?id=2553
题意:给一个无向图,如果一个点v能够到达w并且w也能到v则w和v都称为一个sink,题目要求从大到小输出图中所有的sink点。注意叶子结点都是sink点。
思路:正如上面说的叶子结点都是sink,而且只有叶子结点才能形成sink点。因而先进行缩点,然后再求叶子结点。

#include<set> #include<map> #include<stack> #include<queue> #include<cmath> #include<bitset> #include<string> #include<climits> #include<cstdio> #include<vector> #include<utility> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define IN puts("in") #define OUT puts("out") #define FR(x) freopen(x,"r",stdin) #define FW(x) freopen(x,"w",stdout) #define MSET(x,y) memset(x,y,sizeof(x)) #define ST system("pause") using namespace std; const int maxn = 5005; struct nd { int u,v,next; }edge[maxn*100]; int head[maxn],vis[maxn],st[maxn],dfn[maxn],low[maxn],belong[maxn],out[maxn],c[maxn]; int ecnt,cnt,idx,tp; void add(int u,int v) { edge[ecnt].u = u; edge[ecnt].v = v; edge[ecnt].next = head[u]; head[u] = ecnt++; } void tarjan(int u) { int i,v; dfn[u] = low[u] = ++idx; st[++tp] = u; vis[u] = 1; for(i = head[u]; i != -1; i = edge[i].next) { v = edge[i].v; if(!dfn[v]){ tarjan(v); low[u] = min(low[v],low[u]); }else if(vis[v]) low[u] = min(dfn[v],low[u]); } if(dfn[u] == low[u]) { cnt++; do{ v = st[tp--]; vis[v] = 0; belong[v] = cnt; }while(v!=u); } } void processing() { int i,j,k,n,m,u,v; while(scanf("%d",&n)==1) { if(!n)return ; scanf("%d",&m); MSET(vis,0); MSET(dfn,0); MSET(belong,0); MSET(out,0); MSET(head,-1); ecnt = cnt = idx = tp = 0; for(i = 0; i < m; ++ i) { scanf("%d %d",&u,&v); add(u,v); } for(i = 1; i <= n; ++ i) if(!dfn[i]) tarjan(i); for(i = 0; i < m; ++ i) { u = belong[edge[i].u]; v = belong[edge[i].v]; if(u!=v)out[u]++; } k = 0; for(i = 1; i <= n; ++ i){j = belong[i]; if(!out[j]) c[k++] = i;} for(i = 0; i < k - 1; ++ i) printf("%d ",c[i]);printf("%d\n",c[i]); } } int main() { processing(); return 0; }