头部背景图片
Decaku 's Blog |
Decaku 's Blog |

Poj 2186 Popular Cows

描述:

$有若干cows,如果a崇拜b,b崇拜c那么a崇拜c,求有多少cows \\
被其他的所有cows崇拜。$


思路:

$建立有向图,然后缩点,需要找的点就是出度为0的点。 \\
证明:若有一点a出度不为0且a到b有一条边,由于是DAG \\
可知不存在从b到a的路径,所以a不是所求点,又发现若 \\
出度为0的点数量大于1时必然不满足题意,这些点之间不 \\
存在有向边。$


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=20005;
const int maxm=50005;
struct Edge
{
int to,next;
} edge[maxm];

int head[maxn],tot;
int index,top;
int Low[maxn],Dfn[maxn],Stack[maxn],Belong[maxn];
int mark[maxn];

int scc;
bool Instack[maxn];
int num[maxn];
int n,m,x,y;

void addedge(int u,int v)
{
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void Tarjan(int u)
{
int v;
Low[u]=Dfn[u]=++index;
Stack[top++]=u;
Instack[u]=true;
for(int i=head[u]; i!=-1; i=edge[i].next)
{
v=edge[i].to;
if(!Dfn[v])
{
Tarjan(v);
if(Low[u]>Low[v]) Low[u]=Low[v];
}
else if(Instack[v]&&Low[u]>Dfn[v]) Low[u]=Dfn[v];
}
if(Low[u]==Dfn[u])
{
scc++;
do
{
v=Stack[--top];
Instack[v]=false;
Belong[v]=scc;
num[scc]++;
}
while(v!=u);
}
}
void solve(int n)
{
memset(Dfn,0,sizeof(Dfn));
memset(Low,0,sizeof(Low));
memset(Instack,false,sizeof(Instack));
memset(num,0,sizeof(num));
memset(mark,0,sizeof(mark));
index=scc=top=0;
for(int i=1; i<=n; i++)
if(!Dfn[i])
Tarjan(i);
for(int i=1; i<=n; i++)
for(int j=head[i]; j!=-1; j=edge[j].next)
{
if(Belong[i]!=Belong[edge[j].to])
mark[Belong[i]]=true;
}
int pos=0,lab=0;
for(int i=1; i<=scc; i++)
if(!mark[i])
{
lab++;
pos=i;
}
if(lab>1)printf("0\n");
else printf("%d\n",num[pos]);

}
int main()
{
scanf("%d%d",&n,&m);
tot=0;
memset(head,-1,sizeof(head));
for(int i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);
}
solve(n);
}
avatar Decaku 菜菜菜