BZOJ 1051 受欢迎的牛 缩点

题目链接:

https://www.lydsy.com/JudgeOnline/problem.php?id=1051

题目大意:

每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。
思路:
进行缩点,之后变成DAG图,记录出度为0的点,如果只有一个说明有解,否则答案为0。
统计那个出度为0的强连通分量内的点的数目即可。
 1 #include<bits/stdc++.h>
 2 #define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
 3 #define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
 4 #define Min(a, b) ((a) < (b) ? (a) : (b))
 5 #define Mem(a) memset(a, 0, sizeof(a))
 6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
 7 #define MID(l, r) ((l) + ((r) - (l)) / 2)
 8 #define lson ((o)<<1)
 9 #define rson ((o)<<1|1)
10 #pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
11 using namespace std;
12 inline int read()
13 {
14     int x=0,f=1;char ch=getchar();
15     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
16     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
17     return x*f;
18 }
19 
20 typedef long long ll;
21 const int maxn = 10000 + 10;
22 const int mod = 100003;//const引用更快,宏定义也更快
23 const int INF = 1e9;
24 vector<int>G[maxn];
25 int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt;
26 stack<int>S;
27 void dfs(int u)
28 {
29     pre[u] = lowlink[u] = ++dfs_clock;
30     S.push(u);
31     for(int i = 0; i < G[u].size(); i++)
32     {
33         int v = G[u][i];
34         if(!pre[v])
35         {
36             dfs(v);
37             lowlink[u] = Min(lowlink[u], lowlink[v]);
38         }
39         else if(!sccno[v])
40         {
41             lowlink[u] = Min(lowlink[u], pre[v]);
42         }
43     }
44     if(lowlink[u] == pre[u])
45     {
46         scc_cnt++;
47         for(;;)
48         {
49             int x = S.top();
50             S.pop();
51             sccno[x] = scc_cnt;
52             if(x == u)break;
53         }
54     }
55 }
56 void find_scc(int n)
57 {
58     dfs_clock = scc_cnt = 0;
59     Mem(sccno);
60     Mem(pre);
61     for(int i = 0; i < n; i++)if(!pre[i])dfs(i);
62 }
63 int chu[maxn];
64 int main()
65 {
66     int n, m, u, v;
67     scanf("%d%d", &n, &m);
68     while(m--)
69     {
70         scanf("%d%d", &u, &v);
71         u--, v--;
72         G[u].push_back(v);
73     }
74     find_scc(n);
75     for(int u = 0; u < n; u++)
76     {
77         for(int i = 0; i < G[u].size(); i++)
78         {
79             int v = G[u][i];
80             if(sccno[u] != sccno[v])
81             {
82                 chu[sccno[u]]++;
83             }
84         }
85     }
86     int tot = 0, t;
87     for(int i = 1; i <= scc_cnt; i++)
88         if(chu[i] == 0)tot++, t = i;
89     int ans = 0;
90     if(tot == 1)
91     {
92         for(int i = 0; i < n; i++)
93         {
94             if(sccno[i] == t)ans++;
95         }
96     }
97     printf("%d\n", ans);
98     return 0;
99 }

 

posted @ 2018-09-11 16:04  _努力努力再努力x  阅读(147)  评论(0编辑  收藏  举报