您的位置:首页 > 其它

POJ2553 The Bottom of a Graph(强连通分量+缩点)

2016-01-25 10:57 260 查看
题目是问,一个有向图有多少个点v满足∀w∈V:(v→w)⇒(w→v)。

把图的强连通分量缩点,那么答案显然就是所有出度为0的点。

用Tarjan找强连通分量:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 5555
#define MAXM 5555*5555
struct Edge{
int u,v,next;
}edge[MAXM];
int NE,head[MAXN];
void addEdge(int u,int v){
edge[NE].u=u; edge[NE].v=v; edge[NE].next=head[u];
head[u]=NE++;
}

int bn,belong[MAXN],stack[MAXN],top;
bool instack[MAXN];
int dn,dfn[MAXN],low[MAXN];
void dfs(int u){
dfn[u]=low[u]=++dn;
stack[++top]=u; instack[u]=1;
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(dfn[v]==0){
dfs(v);
low[u]=min(low[u],low[v]);
}else if(instack[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
int v; ++bn;
do{
v=stack[top--];
instack[v]=0;
belong[v]=bn;
}while(u!=v);
}
}

int deg[MAXN];
int main(){
int n,m,a,b;
while(~scanf("%d",&n) && n){
NE=0;
memset(head,-1,sizeof(head));
scanf("%d",&m);
while(m--){
scanf("%d%d",&a,&b);
addEdge(a,b);
}
top=dn=bn=0;
memset(dfn,0,sizeof(dfn));
memset(instack,0,sizeof(instack));
for(int i=1; i<=n; ++i){
if(dfn[i]==0) dfs(i);
}
memset(deg,0,sizeof(deg));
for(int i=0; i<NE; ++i){
int u=belong[edge[i].u],v=belong[edge[i].v];
if(u==v) continue;
++deg[u];
}
bool first=1;
for(int i=1; i<=n; ++i){
if(deg[belong[i]]==0){
if(first) first=0;
else putchar(' ');
printf("%d",i);
}
}
putchar('\n');
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: