【POJ2186 最受欢迎的牛】

题目大意:

      每一头牛的愿望就是变成一头最受欢迎的牛。现在有N(1<=N<=10000)头牛,给你M(1<=M<=50000)对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。

输入格式:

  第一行输入n,m

  下面m行每行输入x,y表示x到y有一条边

输出格式:

  输出受欢迎奶牛的数量

输入样例

  3 3
  1 2
  2 1
  2 3

输出样例

  1

题解

  先tarjan缩点,对于新建的图中,出度为0的点如果只有一个,说明这个点(缩过)被所有奶牛欢迎。否则的话就不可能有奶牛被所有的牛认为是受欢迎。

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<algorithm>
 6 struct nd1
 7 {
 8     int next,to;
 9 }    e1[150005];
10 int head[110005],out[110005],sc,cnt;
11 inline void insert(int u,int v)
12 {
13     e1[++cnt].next=head[u];
14     head[u]=cnt;
15     e1[cnt].to=v;
16 }
17 int time,s[110005],vis[110005],dfn[110005],low[110005],bl[110005],num[110005];
18 int n,m;
19 inline void tarjan(int now)
20 {
21     dfn[now]=low[now]=++time;
22     s[++s[0]]=now;vis[now]=1;
23     for(int i=head[now];i;i=e1[i].next)
24     {
25         if(!dfn[e1[i].to])
26         {
27             tarjan(e1[i].to);
28             low[now]=std::min(low[now],low[e1[i].to]);
29         }
30         else    if(vis[e1[i].to])
31             low[now]=std::min(low[now],dfn[e1[i].to]);
32     }
33     if(dfn[now]==low[now])
34     {
35         num[bl[now]=++sc]=1;
36         vis[now]=0;
37         while(s[s[0]]!=now)
38         {
39             vis[s[s[0]]]=0;
40             bl[s[s[0]]]=sc;
41             num[sc]++;
42             s[0]--;
43         }
44         s[0]--;
45     }
46 }
47 inline void rdeg()
48 {
49     for(int i=1;i<=n;i++)
50         for(int j=head[i];j;j=e1[j].next)
51         {
52             if(bl[i]!=bl[e1[j].to])
53                 out[bl[i]]++;
54         }
55 }
56 int main()
57 {
58     int u,v;
59     scanf("%d%d",&n,&m);
60     for(int i=1;i<=m;i++)
61     {
62         scanf("%d%d",&u,&v);
63         insert(u,v);
64     }
65     for(int i=1;i<=n;i++)
66         if(!dfn[i])    tarjan(i);
67     rdeg();
68     int ans=0;
69     for(int i=1;i<=sc;i++)
70     {
71         if(!out[i] && !ans)    ans=num[i];
72         else    if(!out[i] && ans!=0)
73         {
74             ans=-1;
75             break; 
76         }
77     }
78     if(ans==-1)    puts("0\n");
79     else    printf("%d\n",ans);
80     return 0;
81 }

 

转载于:https://www.cnblogs.com/Dndlns/p/7857617.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值