ybtoj强连通分块Tarjan例题2受欢迎的牛
Posted SSL_ZZL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ybtoj强连通分块Tarjan例题2受欢迎的牛相关的知识,希望对你有一定的参考价值。
Link
解题思路
先Tarjan,把牛进行捆绑
(在一个强连通分块中,如果一个牛是明星,那么其他的牛也一定是明星)
考虑明星的的条件
- 在出度为0的强连通分块中
(如果这个分块喜欢另一个分块的牛,因为是两个分块,所以另一个分块的牛一定不喜欢这个分块的牛,不然互相喜欢,就是一个强连通分块了) - 出度为0的强连通分块只有一个
(如果出现两个出度为0的强连通分块,那这两个分块的牛不喜欢对方,那么就没有牛是明星)
Code
#include <iostream>
#include <cstdio>
using namespace std;
struct DT{
int to, next;
}Ta[500000];
int n, m, dye, ans, Tnum, now, top, x, y, s[10100], times[10100];
int Ts[10100], Thead[10100], low[10100], dfn[10100], hep[10100], co[10100];
void Tarjan(int x) {
dfn[x] = low[x] = ++now;
hep[++top] = x;
for (int i = Thead[x]; i; i = Ta[i].next)
if(!dfn[Ta[i].to]) {
Tarjan(Ta[i].to);
low[x] = min(low[x], low[Ta[i].to]);
} else if (!co[Ta[i].to])
low[x] = min(low[x], dfn[Ta[i].to]);
if(dfn[x] == low[x]) {
co[x] = ++dye;
s[dye]++; //统计分块中的牛
while(hep[top] != x)
co[hep[top--]] = dye, s[dye]++;
--top;
}
}
int main() {
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; i++) {
scanf("%d %d", &x, &y);
Ta[++Tnum] = (DT){y, Thead[x]};
Thead[x] = Tnum;
}
for(int i = 1; i <= n; i++)
if (!dfn[i])
Tarjan(i);
for (int i = 1; i <= n; i++)
for (int j = Thead[i]; j; j = Ta[j].next)
if (co[i] != co[Ta[j].to])
times[co[i]]++; //统计出度
for (int i = 1; i <= dye; i++)
if(!times[i]) { //1.明星在出度为0的强连通分块中
if (!ans) //2.出度为0的强连通分块只有一个
ans = i;
else ans = -1; //如果有多个出度为0的强连通分块, 那么就没有牛是明星
}
if (ans == -1) printf("0");
else printf("%d", s[ans]); //出度为0的强连通分块中所有的牛都是明星
}
以上是关于ybtoj强连通分块Tarjan例题2受欢迎的牛的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ10511051: [HAOI2006]受欢迎的牛 tarjan求强连通分量+缩点