[USACO08DEC]在农场万圣节Trick or Treat on the Farm 题解

题目大意:有n个点,每个点会有1条连出去的边(注意,连向这个点的边数不一定是1),有n头牛,第i头牛从i点开始出发,无脑往前沿着边走,问每头牛能经过多少个不同的点(起点也要算!!)。

细细品味一下这个题目,就可以发现构造出来的图会有环,因为环中的节点都不可能还有向外连出去的边,所以环中的节点总数便是环中每一个节点的ans,那么,其他连到这个环里的点的ans便是环中节点的ans+1,连到这个点的点就是这个点的ans+1……以此类推,所以,其实只要简单的把图搜一遍就好了。

附上代码:

#include
#include


int n,t=0,m=0;
int next[100010]; 
int f[100010];//ans数组 
int q[100010];//记录每一个节点在dfs中出现的顺序 
void dfs(int x)
{
if(x==next[x])//自环
{
f[x]=1;
return;
}
if(f[next[x]]!=0)//假如前面的节点已经被搜过
{
f[x]=f[next[x]]+1;
return;
}
else
{
q[x]=++t;
if(q[next[x]]!=0)//假如前面的节点在这次dfs时被搜过,那么说明找到了一个环
{
f[x]=f[next[x]]=t-q[next[x]]+1;//t-q[next[x]]+1表示这个环包含几个点
m=t-q[next[x]]+1;//m用来给环中的其他节点赋值
return;
}
dfs(next[x]);
if(f[x]==0&&m!=0)f[x]=m;//假如这个节点在环中
else
{
m=0;
if(f[x]==0)f[x]=f[next[x]]+1;
}
}
}


int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&next[i]);
memset(q,0,sizeof(q));
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
{
if(f[i]==0)t=0,dfs(i);
printf("%d\n",f[i]);
}
}

你可能感兴趣的:(题解_杂)