题意:有些牛有自己的偶像,偶像的偶像也是自己的偶像,问存在多少牛被所有牛崇拜。
题解:牛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;
}
本文介绍了一种用于解决牛群偶像崇拜问题的强连通分量算法。通过建立有向图并使用Tarjan算法求解强连通分量,可以找出哪些牛被所有其他牛视为偶像。文章提供了详细的Tarjan算法实现代码,并解释了如何确定最终的答案。
4677

被折叠的 条评论
为什么被折叠?



