题目链接:
http://poj.org/problem?id=2186
题意:
有一群喜欢互相崇拜的牛,让你输出会被其他所有牛崇拜的牛的数量。
题解:
这里很容易想到用强连通进行缩点(因为在这个强连通分量里面的牛是被互相崇拜的,可以直接看成一只牛),题目中说道,这只牛被所有的牛崇拜,因此,也不难想到这牛是不会崇拜其他牛的。因为根据强连通缩点的性质,在完成缩点之后,这个图就变成了有向无环图。因此只要考虑点出度的问题就行了。
Tarjan模版:
stack<int> s;
vector<int> v[maxn2];
bool instack[maxn1];
int dfn[maxn1],low[maxn1];
int belong[maxn1];//缩点存储
int degree[maxn1];
int cnt1;//更新
int cnt2;//计算有几个满足条件
int n,m;
void scc(int x)
{
dfn[x]=low[x]=cnt1++;
instack[x]=true;
s.push(x);
for(int i=0;i<v[x].size();i++)
{
int y=v[x][i];
if(dfn[y]==-1)
{
scc(y);
low[x]=min(low[x],low[y]);
}
else if(instack[y])
{
low[x]=min(low[x],dfn[y]);
}
}
if(dfn[x]==low[x])
{
int z;
do
{
z=s.top();
s.pop();
instack[z]=false;
belong[z]=cnt2;
}
while(x!=z);
cnt2++;
}
}
void Tarjan()
{
while(!s.empty())
s.pop();
met(dfn,-1);
met(low,inf);
met(belong,-1);
cnt1=0;
cnt2=0;
for(int i=0;i<n;i++)
{
if(dfn[i]==-1)
scc(i);
}
}
代码:
#include <cstdio>
#include <stack>
#include <map>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
const int maxn1 =1e4+10;
const int maxn2 =5e4+10;
stack<int> s;
vector<int> v[maxn2];
bool instack[maxn1];
int dfn[maxn1],low[maxn1];
int belong[maxn1];//缩点存储
int degree[maxn1];
int cnt1;//更新
int cnt2;//计算有几个满足条件
int n,m;
void scc(int x)
{
dfn[x]=low[x]=cnt1++;
instack[x]=true;
s.push(x);
for(int i=0;i<v[x].size();i++)
{
int y=v[x][i];
if(dfn[y]==-1)
{
scc(y);
low[x]=min(low[x],low[y]);
}
else if(instack[y])
{
low[x]=min(low[x],dfn[y]);
}
}
if(dfn[x]==low[x])
{
int z;
do
{
z=s.top();
s.pop();
instack[z]=false;
belong[z]=cnt2;
}
while(x!=z);
cnt2++;
}
}
void Tarjan()
{
while(!s.empty())
s.pop();
met(dfn,-1);
met(low,inf);
met(belong,-1);
cnt1=0;
cnt2=0;
for(int i=0;i<n;i++)
{
if(dfn[i]==-1)
scc(i);
}
}
void slove()
{
Tarjan();
met(degree,0);
// 判定计算出度值
for(int i=0;i<n;i++)
{
for(int j=0;j<v[i].size();j++)
{
int k=v[i][j];
if(belong[i]!=belong[k])
degree[belong[i]]++;
}
}
int num=0;
int pos=0;
for(int i=0;i<cnt2;i++)
{
if(degree[i]==0)
{
pos=i;
num++;
}
}
if(num!=1)
{
printf("0\n");
}
else
{
int ans=0;
for(int i=0;i<n;i++)
{
if(belong[i]==pos)
ans++;
}
printf("%d\n",ans);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
a--;
b--;
// 从0——N-1;
v[a].push_back(b);
}
slove();
}