信息传递
信息传递
思路
仔细思考,这道题应该是一道图,就类似找环的操作,找到连成的最小的环。
每个人将自己的信息传递给自己的信息传递对象,具有专一性,每个人只能传递给另一个人,出度只为一,而入度则可以有很多个。当把内些入度为零得店全部删除之后,就会变成若干个不相连的环(出度永远为一,而删去其他得没有出度的点之后,入度也将会变成一)
这个时候呢,就可以dfs了!!!
附上代码(ac代码噢)
#include<bits/stdc++.h>
using namespace std;
int n;
int t[201000];//被传递者
int r[201000];//入度
int d[201000];//是否被标记(包括被删除和被查找到的)
int ans=10000000;//附上极大值方便比较最小的环
void dfs(int x,int s,int l)//x在这里是传递者,s算是对照实验中的对照组,而l就是每个环的长度
{
if(t[x]==s&&l!=0)//被传递者等于自己本身,也算是形成了一个环(主要还是因为,下面我提前标记了一下x这个数,导致不可能再回到x本身*)
{
ans=min(ans,l+1);
return ;
}
d[x]=1;
if(d[t[x]]==0)//这点要特别注意,因为我就是这点出过了问题,这个时候只需要d数组中他的值为0即可代表他没有被删除,也没有被查找过
dfs(t[x],s,l+1);//继续循环
}
void remove(int x)
{
d[x]=-1;//标记被删除
r[t[x]]--;
if(r[t[x]]==0&&d[t[x]]!=-1)//下一个的入度为零,继续删除
remove(t[x]);
}
int main()
{
memset(t,0,sizeof(t));
memset(r,0,sizeof(r));
memset(d,0,sizeof(d));//清零,清零,清零
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&t[i]);
r[t[i]]++;//入度加一 ,因为此时进入的每一个数都是被传递者,所以他们肯定会有入度
}
for(int i=1;i<=n;i++)//删除内些入度为0的
{
if(r[i]==0&&d[i]!=-1)
remove(i);
}
for(int i=1;i<=n;i++)
{
if(d[i]==0)//这点也要注意啊,理由同dfs中
dfs(i,i,0);
}
cout<<ans<<endl;
return 0;
}