| Time Limit: 3000MS | Memory Limit: 65536K | |
| Total Submissions: 9779 | Accepted: 4063 |
Description
Input
Output

Sample Input
3 3 1 3 2 3 3 1 2 1 1 2 0
Sample Output
1 3 2
题意:给定一幅有向图,若某点所能到达的点也能到达其本身,那么这个点为sink。由小到大输出sink.
思路:有向图缩点得到一棵树,答案为构成叶子(出度为0)结点的连通分量。
#include"cstdio" #include"cstring" #include"algorithm" #include"vector" using namespace std; const int MAXN=5005; struct Edge{ int to,next; }es[MAXN*MAXN]; int V,E; int head[MAXN],ant; void add_edge(int u,int v) { es[ant].to=v; es[ant].next=head[u]; head[u]=ant++; } int index; int dfn[MAXN],low[MAXN]; int stack[MAXN],top; int cpnt[MAXN],cnt; void tarjan(int u) { stack[top++]=u; dfn[u]=low[u]=++index; for(int i=head[u];i!=-1;i=es[i].next) { int to=es[i].to; if(!dfn[to]) { tarjan(to); low[u]=min(low[u],low[to]); } else low[u]=min(low[u],dfn[to]); } if(dfn[u]==low[u]) { int v; cnt++; do{ v=stack[--top]; cpnt[v]=cnt; }while(u!=v); } } int deg[MAXN]; int res[MAXN]; int s; void seek() { for(int i=1;i<=V;i++) { for(int j=head[i];j!=-1;j=es[j].next) { int to=es[j].to; if(cpnt[i]!=cpnt[to]) { deg[cpnt[i]]++; } } } for(int i=1;i<=V;i++) { if(deg[cpnt[i]]==0) { res[s++]=i; } } } int main() { while(scanf("%d",&V)!=EOF&&V) { scanf("%d",&E); s=0; memset(head,-1,sizeof(head)); ant=0; index=0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); top=0; memset(cpnt,0,sizeof(cpnt)); cnt=0; memset(deg,0,sizeof(deg)); for(int i=0;i<E;i++) { int u,v; scanf("%d%d",&u,&v); add_edge(u,v); } for(int i=1;i<=V;i++) if(!dfn[i]) tarjan(i);//注意无向图与有向图的缩点方式 seek(); if(s==0) { printf("\n"); } else { for(int i=0;i<s-1;i++) { printf("%d ",res[i]); } printf("%d\n",res[s-1]); } } return 0; }
下面是kosaraju算法
#include"cstdio" #include"cstring" #include"vector" using namespace std; const int MAXN=5005; vector<int> G[MAXN]; vector<int> rG[MAXN]; vector<int> vs; int V,E; int cpnt[MAXN]; int vis[MAXN]; void dfs(int u) { vis[u]=1; for(int i=0;i<G[u].size();i++) if(!vis[G[u][i]]) dfs(G[u][i]); vs.push_back(u); } void rdfs(int u,int k) { cpnt[u]=k; vis[u]=1; for(int i=0;i<rG[u].size();i++) if(!vis[rG[u][i]]) rdfs(rG[u][i],k); } void scc() { memset(vis,0,sizeof(vis)); for(int i=1;i<=V;i++) if(!vis[i]) dfs(i); memset(vis,0,sizeof(vis)); int k=1; for(int i=vs.size()-1;i>=0;i--) if(!vis[vs[i]]) rdfs(vs[i],k++); } int deg[MAXN]; void solve() { scc(); for(int i=1;i<=V;i++) { for(int j=0;j<G[i].size();j++) { int to=G[i][j]; if(cpnt[i]!=cpnt[to]) { deg[cpnt[i]]++; } } } int flag=0; for(int i=1;i<=V;i++) { if(deg[cpnt[i]]==0) { if(flag==0) { printf("%d",i); flag=1; } else { printf(" %d",i); } } } printf("\n"); } int main() { while(scanf("%d",&V)!=EOF&&V) { scanf("%d",&E); vs.clear(); memset(cpnt,0,sizeof(cpnt)); memset(deg,0,sizeof(deg)); for(int i=1;i<=V;i++) { G[i].clear(); rG[i].clear(); } for(int i=0;i<E;i++) { int u,v; scanf("%d%d",&u,&v); G[u].push_back(v); rG[v].push_back(u); } solve(); } return 0; }
原文:http://www.cnblogs.com/program-ccc/p/5169604.html