题目大意
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果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 "); else printf("%d ", GetAns()); return 0; }