poj 2186 (强连通分支)

题意:每头牛都想成为牛群中的红人。给N头牛的的牛群和M个有序对(A,B)。(A,B)表示牛A认为B是红人。该关系具有传递性,所以如果牛A认为B是红人,牛B认为牛C是红人,那么牛A也认为牛C是红人。不过,给定的有序对中可能包含(A,B)和(B,C),但不包含(A,C)。求被其他牛认为是红人的总数。

思路:方法是是找到拓扑排序最后的那个强连通分量在统计他是不是能访问到所有的结点就OK了。

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <queue>
 8 #include <stack>
 9 #include <vector>
10 #define MP(a, b) make_pair(a, b)
11 #define PB(a) push_back(a)
12 
13 using namespace std;
14 
15 typedef long long ll;
16 typedef pair<int ,int> pii;
17 typedef pair<unsigned int, unsigned int> puu;
18 typedef pair<int ,double> pid;
19 typedef pair<ll, int> pli;
20 
21 const int INF = 0x3f3f3f3f;
22 const double eps = 1e-6;
23 const int LEN = 10000+10;
24 int vis[LEN], n, m, cmp[LEN];
25 vector<int> Map[LEN], rMap[LEN], vs;
26 
27 void dfs(int v)
28 {
29     vis[v] = 1;
30     for(int i=0; i<Map[v].size(); i++){
31         if(!vis[Map[v][i]])dfs(Map[v][i]);
32     }
33     vs.PB(v);
34 }
35 
36 void rdfs(int v, int k)
37 {
38     vis[v] = 1;
39     cmp[v] = k;
40     for(int i=0; i<rMap[v].size(); i++){
41         if(!vis[rMap[v][i]])rdfs(rMap[v][i], k);
42     }
43 }
44 
45 int scc()
46 {
47     memset(vis, 0, sizeof vis);
48     vs.clear();
49     for(int i=1; i<=n; i++){
50         if(!vis[i])dfs(i);
51     }
52     memset(vis, 0, sizeof vis);
53     int k = 0;
54     for(int i=vs.size()-1; i>=0; i--){
55         if(!vis[vs[i]])rdfs(vs[i], k++);
56     }
57     return k;
58 }
59 
60 int main()
61 {
62 //    freopen("in.txt", "r", stdin);
63 
64     int a, b;
65     while(scanf("%d%d", &n, &m)!=EOF){
66         for(int i=0; i<LEN; i++)Map[i].clear();
67         for(int i=0; i<LEN; i++)rMap[i].clear();
68         for(int i=0; i<m; i++){
69             scanf("%d%d", &a, &b);
70             Map[a].PB(b);
71             rMap[b].PB(a);
72         }
73         int num = scc(), ans = 0, u = 0;
74         for(int i=1; i<=n; i++)if(cmp[i] == num-1){u = i;ans++;}
75         memset(vis, 0, sizeof vis);
76         rdfs(u, 0);
77         for(int i=1; i<=n; i++)if(!vis[i])ans = 0;
78         printf("%d\n", ans);
79     }
80     return 0;
81 }
View Code

 

 

转载于:https://www.cnblogs.com/shu-xiaohao/p/3525857.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值