2015noip

信息传递

在这里插入图片描述

思路

仔细思考,这道题应该是一道图,就类似找环的操作,找到连成的最小的环。
每个人将自己的信息传递给自己的信息传递对象,具有专一性,每个人只能传递给另一个人,出度只为一,而入度则可以有很多个。当把内些入度为零得店全部删除之后,就会变成若干个不相连的环(出度永远为一,而删去其他得没有出度的点之后,入度也将会变成一)
这个时候呢,就可以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;
	} 

跳石头

思路

哇,这个思路简直卡掉了楼主好长时间(显然,楼主是个蒟蒻),最后还是看到了洛谷上的题解

猜你喜欢

转载自blog.csdn.net/qq_43093454/article/details/83747887
今日推荐