码迷,mamicode.com
首页 > 移动开发 > 详细

POJ 2186 Popular Cows(强联通分量)

时间:2018-03-24 00:43:52      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:scanf   ios   name   访问   包含   int   popular   思路   return   

题目链接:http://poj.org/problem?id=2186

题目大意:

   每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
牛被所有的牛认为是受欢迎的。
解题思路:
假设有两头牛A和B都被其他所有牛认为是红人,那么显然,A被B认为是红人,B也被A认为是红人,即存在一个包含A、B两个顶点的圈,或者说,A、B同属于一个强联通分量。所以
如果有一头牛被其他所有牛认为是红人,那么其所属的强联通分量内的所有牛都被其他所有牛认为是红人。我们把图进行强联通分量分解后,至多有一个强联通分量满足题目的条件。
做法: 先用tarjan求出每个强连通分量,再缩点,统计每个点的出度,如果有且只有1个出度为0的点,就输出这个点包含的节点数,否则输出0。
代码
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<stack>
 7 using namespace std;
 8 const int N=1e4+5;
 9 
10 int cnt,num;
11 int dfn[N],low[N],fa[N],sze[N],outdeg[N];
12 stack<int>sk;
13 vector<int>v[N];
14 
15 void tarjan(int u){
16     dfn[u]=low[u]=++cnt;
17     sk.push(u);
18     for(int i=0;i<v[u].size();i++){
19         int t=v[u][i];
20         if(!dfn[t]){                                        //点t未被访问
21             tarjan(t);
22             low[u]=min(low[u],low[t]);
23         }
24         else if(!fa[t])  low[u]=min(low[u],dfn[t]);         //点t已被访问,且t还在栈中
25     }
26     if(low[u]==dfn[u]){
27         num++;
28         while(1){
29             int t=sk.top();
30             sk.pop();
31             fa[t]=num;                                      //缩点操作,将这些点都归为点num
32             sze[num]++;
33             if(t==u) break;
34         }
35     }
36 }
37 
38 int main(){
39     int n,m;
40     scanf("%d%d",&n,&m);
41     for(int i=1;i<=m;i++){
42         int a,b;
43         scanf("%d%d",&a,&b);
44         v[a].push_back(b);
45     }
46     for(int i=1;i<=n;i++){
47         if(!dfn[i]) tarjan(i);
48     }
49     for(int i=1;i<=n;i++){
50         for(int j=0;j<v[i].size();j++){
51             int t=v[i][j];
52             if(fa[t]!=fa[i]) outdeg[fa[i]]++;
53         }
54     }
55     //缩点后,出度为0的点只能有一个,否则不符合条件输出0
56     int ans=0;
57     for(int i=1;i<=num;i++){
58         if(!outdeg[i]){
59             if(ans>0){
60                 puts("0");
61                 return 0;
62             }
63             ans=sze[i];
64         }
65     }
66     printf("%d\n",ans);
67     return 0;
68 }

 

 
 

POJ 2186 Popular Cows(强联通分量)

标签:scanf   ios   name   访问   包含   int   popular   思路   return   

原文地址:https://www.cnblogs.com/fu3638/p/8635597.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!