luogu2341 [HAOI2006]受欢迎的牛
题目大意
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你算出有多少头奶牛可以当明星。
思路

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
#include <cassert>
using namespace std;
const int MAX_NODE = 10010;
struct Block
{
int Size;
bool NotLeaf;
}_blocks[MAX_NODE];
int _blockCnt;
struct Node
{
int Low, DfsN;
bool InStack;
vector<Node*> Next;
Block* BlockIn;
}_nodes[MAX_NODE];
int _vCount, DfsCnt;
stack<Node*> St;
void PopStack(Node *cur)
{
Block *curBlock = _blocks + ++_blockCnt;
Node *temp;
do {
temp = St.top();
temp->InStack = false;
St.pop();
temp->BlockIn = curBlock;
curBlock->Size++;
} while (temp != cur);
}
void Dfs(Node *cur)
{
cur->Low = cur->DfsN = ++DfsCnt;
cur->InStack = true;
St.push(cur);
for (unsigned int i = 0; i < cur->Next.size(); i++)
{
if (!cur->Next[i]->DfsN)
{
Dfs(cur->Next[i]);
cur->Low = min(cur->Low, cur->Next[i]->Low);
}
else if (cur->Next[i]->InStack)
cur->Low = min(cur->Low, cur->Next[i]->DfsN);
}
if (cur->Low == cur->DfsN)
PopStack(cur);
}
void Tarjan()
{
for (int i = 1; i <= _vCount; i++)
{
if (!_nodes[i].DfsN)
Dfs(_nodes + i);
assert(St.size() == 0);
}
}
int GetLeafCnt()
{
int leafCnt = 0;
for (int i = 1; i <= _vCount; i++)
for (unsigned int j = 0; j < _nodes[i].Next.size(); j++)
if (_nodes[i].BlockIn != _nodes[i].Next[j]->BlockIn)
_nodes[i].BlockIn->NotLeaf = true;
for (int i = 1; i <= _blockCnt; i++)
leafCnt += !_blocks[i].NotLeaf;
return leafCnt;
}
int GetAns()
{
for (int i = 1; i <= _blockCnt; i++)
if (!_blocks[i].NotLeaf)
return _blocks[i].Size;
return -1;
}
int main()
{
int totEdge;
scanf("%d%d", &_vCount, &totEdge);
for (int i = 1; i <= totEdge; i++)
{
int u, v;
scanf("%d%d", &u, &v);
_nodes[u].Next.push_back(_nodes + v);
}
Tarjan();
int leafCnt = GetLeafCnt();
if (leafCnt > 1)
printf("0\n");
else
printf("%d\n", GetAns());
return 0;
}

浙公网安备 33010602011771号