bzoj 1051: [HAOI2006]受欢迎的牛

来源:互联网 发布:数据库营销系统 编辑:程序博客网 时间:2024/06/03 04:09

1051: [HAOI2006]受欢迎的牛

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 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];elseans = 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;}}


原创粉丝点击