題意:有些牛有自己的偶像,偶像的偶像也是自己的偶像,問存在多少牛被所有牛崇拜。
題解:牛a崇拜牛b就連一條a指向b的邊,然後找出所有的強連通分量(即這個分量裏的每個點都可以到達分量中的任意一個點)。判斷有沒有出度爲0的強連通分量,而且這個點只有一個,如果有,那麼答案就是這個強連通分量裏面點的個數。
順便可以把這個作爲強連通分量的模板。
先放一個tarjan 強連通分量模板
struct recordtime
{
int index,low;
}tour[SIZE_N];
stack<int>sta;
int vernum,edgnum,Dindex,
scc;
int used[SIZE_N],instack[SIZE_N],
belong[SIZE_N],num[SIZE_M];
void inittarjan()
{
Dindex=0;
scc=0;
memset(used,-1,sizeof(used));
memset(instack,0,sizeof(instack));
memset(belong,0,sizeof(belong));
memset(num,0,sizeof(num));
}
void tarjan(int x)
{
int w,u;
used[x]=1;
tour[x].index=Dindex;
tour[x].low=Dindex;
Dindex++;
sta.push(x);
instack[x]=1;
for(int an=head[x];an!=-1;an=pra[an].next)
{
u=pra[an].to;
if(used[u]==-1)
{
tarjan(u);
tour[x].low=min(tour[x].low,tour[u].low);
}
else
{
//查找棧中的元素
if(instack[u]==1)
tour[x].low=min(tour[x].low,tour[u].index);
}
}
if(tour[x].low==tour[x].index)
{
scc++;
do
{
w=sta.top();
sta.pop();
instack[w]=0;
belong[w]=scc;
num[scc]++;
//printf("%d ",w);
}while(w!=x);
//printf("\n");
}
}
再放一個已經ac的完整代碼
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#define SIZE_N 10100
#define SIZE_M 50100
using namespace std;
struct peck
{
int to,next;
}pra[SIZE_M];
int e,outnum,ang;
int head[SIZE_N],out[SIZE_N];
void init()
{
e=0;
memset(head,-1,sizeof(head));
outnum=0;
ang=0;
memset(out,0,sizeof(out));
}
void addedge(int x,int y)
{
pra[e].to=y;
pra[e].next=head[x];
head[x]=e++;
}
struct recordtime
{
int index,low;
}tour[SIZE_N];
stack<int>sta;
int vernum,edgnum,Dindex,
scc;
int used[SIZE_N],instack[SIZE_N],
belong[SIZE_N],num[SIZE_M];
void inittarjan()
{
Dindex=0;
scc=0;
memset(used,-1,sizeof(used));
memset(instack,0,sizeof(instack));
memset(belong,0,sizeof(belong));
memset(num,0,sizeof(num));
}
void tarjan(int x)
{
int w,u;
used[x]=1;
tour[x].index=Dindex;
tour[x].low=Dindex;
Dindex++;
sta.push(x);
instack[x]=1;
for(int an=head[x];an!=-1;an=pra[an].next)
{
u=pra[an].to;
if(used[u]==-1)
{
tarjan(u);
tour[x].low=min(tour[x].low,tour[u].low);
}
else
{
//查找棧中的元素
if(instack[u]==1)
tour[x].low=min(tour[x].low,tour[u].index);
}
}
if(tour[x].low==tour[x].index)
{
scc++;
do
{
w=sta.top();
sta.pop();
instack[w]=0;
belong[w]=scc;
num[scc]++;
//printf("%d ",w);
}while(w!=x);
//printf("\n");
}
}
void pri()
{
for(int i=1;i<=vernum;i++)
{
printf("the %d th ",i);
for(int an=head[i];an!=-1;an=pra[an].next)
printf("%d ",pra[an].to);
printf("\n");
}
}
int main()
{
int compact,burgeon;
//存圖
while(scanf("%d %d",&vernum,&edgnum)!=EOF)
{
init();
inittarjan();
for (int i = 1;i<=edgnum;i++)
{
scanf("%d %d",&compact,&burgeon);
addedge(compact,burgeon);
}
//pri();
for (int i = 1;i<=vernum;i++)
{
if(used[i]==-1)
tarjan(i);
}
for (int i = 1;i<=vernum;i++)
{
for(int an=head[i];an!=-1;an=pra[an].next)
{
int u=pra[an].to;
int verbe=belong[i];
int tobe=belong[u];
if(verbe!=tobe){
out[verbe]=1;//出度不爲0
//printf("dengyuyi%d\n",u);
}
}
}
for (int i = 1;i<=scc;i++)//這裏i是<=強連通分量的組數
{
//printf("out[%d]=%d\n",i,out[i]);
if(out[i]==0)
{
outnum++;
ang=i;
}//printf("%d\n",ang);
}
if(outnum!=1)//如果出度不爲0的強連通分量有兩個 那說明並不是被所有牛崇拜
num[ang]=0;
printf("%d\n",num[ang]);
}
return 0;
}