poj2186

题意:给出一个有向图,求一共有多少个点,满足这样的条件:所有其它的点都可以到达这个点。

分析:强连通分支+缩点,然后统计每个强连通分支的出度,如果只有一个为0,则输出其内部点的个数,如果有多个为0,说明没有答案。

View Code
#include <iostream>
#include
<cstdlib>
#include
<cstring>
#include
<cstdio>
usingnamespace std;

#define maxn 10005
#define maxm 50005

struct Edge
{
int v, next;
} edge[maxm], opedge[maxm];
int n, m, head[maxn], ophead[maxn], ncount, nowtime, pos[maxn *2], sig[maxn], signnum, in[maxn];
int pointnum[maxn];
bool flag[maxn];
void addedge(int a, int b)
{
edge[ncount].v
= b;
edge[ncount].next
= head[a];
head[a]
= ncount;
opedge[ncount].v
= a;
opedge[ncount].next
= ophead[b];
ophead[b]
= ncount;
ncount
++;
}
void input()
{
scanf(
"%d%d", &n, &m);
for (int i =0; i < m; i++)
{
int a, b;
scanf(
"%d%d", &a, &b);
a
--;
b
--;
addedge(a, b);
}
}
void dfs(int a)
{
flag[a]
=true;
pos[nowtime]
= a;
nowtime
++;
for (int i = head[a]; i !=-1; i = edge[i].next)
if (!flag[edge[i].v])
dfs(edge[i].v);
pos[nowtime]
= a;
nowtime
++;
}
void rdfs(int a)
{
flag[a]
=true;
sig[a]
= signnum;
pointnum[sig[a]]
++;
for (int i = ophead[a]; i !=-1; i = opedge[i].next)
if (!flag[opedge[i].v])
rdfs(opedge[i].v);
}

int main()
{
//freopen("t.txt", "r", stdin);
ncount =0;
memset(head,
-1, sizeof(head));
memset(ophead,
-1, sizeof(ophead));
memset(flag,
0, sizeof(flag));
input();
nowtime
=1;
for (int i =0; i < n; i++)
if (!flag[i])
dfs(i);
memset(flag,
0, sizeof(flag));
memset(pointnum,
0, sizeof(pointnum));
signnum
=0;
for (int i =2* n; i >0; i--)
if (!flag[pos[i]])
{
rdfs(pos[i]);
signnum
++;
}
memset(
in, 0, sizeof(in));
ncount
=0;
for (int i =0; i < n; i++)
for (int j = head[i]; j !=-1; j = edge[j].next)
if (sig[i] != sig[edge[j].v])
in[sig[i]]++;
int ans =-1;
bool ok =true;
for (int i =0; i < signnum; i++)
if (in[i] ==0)
{
if (ans !=-1)
{
ok
=false;
break;
}
ans
= i;
}
if (ok)
printf(
"%d\n", pointnum[ans]);
else
printf(
"0\n");
return0;
}
posted @ 2011-06-05 00:21  金海峰  阅读(897)  评论(0编辑  收藏  举报