#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXE = 22220, MAXV = 11110;
struct Arc
{
int dest;
Arc *next;
inline Arc() {}
inline Arc(const int &_dest, Arc *_next):dest(_dest), next(_next) {}
}Npool[MAXE], *Nptr = Npool, *adj[MAXV];
vector<int> com[MAXV];//存强连通分量的容器
int n, m, dfn[MAXV], low[MAXV], belong[MAXV], index, cnt;
//n顶点数,m边数,index为时间戳,cnt为强连通分量个数
//dfn用来保存时间戳(次序)编号,low保存顶点i或i的子树最早的次序编号
//belong用来缩点的数组,值相等的对应下标在同一个强连通分量内
bool instack[MAXV];
stack<int> s;
inline void addEdge(const int &start, const int &finish)
{
adj[start] = new(Nptr++)Arc(finish, adj[start]);
}
inline void tarjan(const int &i)
{
dfn[i] = low[i] = ++index;
instack[i] = true;
s.push(i);
for (Arc *p = adj[i]; p; p = p->next)
{
if (!dfn[p->dest])
{
tarjan(p->dest);
if (low[i] > low[p->dest])
low[i] = low[p->dest];
}
else if (instack[p->dest])
if (low[i] > dfn[p->dest])
low[i] = dfn[p->dest];
}
if (dfn[i] == low[i])
{
//com[++cnt].clear();
cnt++;//
int j;
do//缩点
{
j = s.top();
s.pop();
instack[j] = false;
com[cnt].push_back(j);
belong[j] = cnt;
}while (j != i);
}
}
int main()
{
scanf("%d", &n);
memset(adj, 0, sizeof(adj));
memset(instack, false, sizeof(instack));
memset(dfn, 0, sizeof(dfn));
index = 0, Nptr = Npool, cnt = 0;
for (int i = 0; i <= n; i++)
com[i].clear();
while (!s.empty())
s.pop();
for (int i = 1; i <= n; i++)
{
int s, t;
while(scanf("%d", &s),s)
addEdge(i, s);
}
for (int i = 1; i <= n; i++)
if (!dfn[i])
tarjan(i);
bool in[MAXV]={0},out[MAXV]={0};
int In=0,Out=0;
for(int i=1;i<=n;i++){
for (Arc *p = adj[i]; p; p = p->next)
if(belong[i]!=belong[p->dest]){
in[belong[p->dest]]=true;//不合要求,要的只是出入度为零的,其余不管
out[belong[i]]=true;
}
}
for(int i=1;i<=cnt;i++){
if(!in[i])In++;
if(!out[i])Out++;
}
cout<<In<<endl<<((cnt==1)?0:max(In,Out))<<endl;//为何min
return 0;
}
poj2186Popular Cows
最新推荐文章于 2017-10-02 11:24:42 发布