1051: [HAOI2006]受欢迎的牛
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 5535 Solved: 2938
[ Submit][ Status][ Discuss]
Description
每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。
Input
第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B)
Output
一个数,即有多少头牛被所有的牛认为是受欢迎的。
Sample Input
3 3
1 2
2 1
2 3
Sample Output
1
求出强联通分量,将每个强联通分量缩成一个点,之候看出度为0的点是否刚好只有一个,
如果只有一个,那么答案就是这个点对应强联通分量中原先点的个数,
如果不只一个,那么答案为0,因为属于出度都为0但不同的点对应的强联通分量里的牛一定不是互相喜欢
#include<stdio.h>
#include<string.h>
#include<stack>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> G[10005], Gn[10005];
stack<int> st;
int t, num, n, low[10005], time[10005], inst[10005], vis[10005], ltt[10005], cnt[10005];
void Trajan(int u);
int main(void)
{
int m, i, j, u, v, now, ans;
while(scanf("%d%d", &n, &m)!=EOF)
{
for(i=1;i<=n;i++)
{
G[i].clear();
Gn[i].clear();
}
for(i=1;i<=m;i++)
{
scanf("%d%d", &u, &v);
G[u].push_back(v);
}
memset(vis, 0, sizeof(vis));
memset(cnt, 0, sizeof(cnt));
t = num = 0;
for(i=1;i<=n;i++)
{
if(vis[i]==0)
Trajan(i);
}
while(st.empty()==0)
{
now = st.top();
st.pop();
ltt[now] = ++num;
cnt[now] = 1;
inst[now] = 0;
}
for(i=1;i<=n;i++)
{
for(j=0;j<G[i].size();j++)
{
v = G[i][j];
if(ltt[i]!=ltt[v])
Gn[ltt[i]].push_back(ltt[v]);
}
}
ans = now = 0;
for(i=1;i<=num;i++)
{
if(Gn[i].size()==0)
{
if(now==0)
now = 1, ans = cnt[i];
else
ans = 0;
}
}
printf("%d\n", ans);
}
return 0;
}
void Trajan(int u)
{
int i, v, now, sum;
time[u] = low[u] = ++t;
vis[u] = inst[u] = 1;
st.push(u);
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
if(vis[v]==0)
{
Trajan(v);
low[u] = min(low[u], low[v]);
}
else if(inst[v]==1)
low[u] = min(low[u], time[v]);
}
if(time[u]==low[u])
{
num++;
sum = 0;
while(st.empty()==0)
{
now = st.top();
inst[now] = 0;
ltt[now] = num;
st.pop();
sum++;
if(now==u)
break;
}
cnt[num] = sum;
}
}