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 }
越努力,越幸运