LUOGU P2661 信息传递

22 篇文章 0 订阅
2 篇文章 0 订阅

信息传递(from luogu)
题面 懒得复制了
在这里插入图片描述在这里插入图片描述

题目分析
根据题意,我们可以将题目中信息传递的路径以图的方式表现出来
同时,信息的传递时单向的
如下图(样例)
在这里插入图片描述
可以很明显的看出,如果符合题意的结束条件便是本人知道自己的信息,也就是走完一个环的流程
但是这个环的长度是有优先之分的,如图:
在这里插入图片描述
可以得到,真正流程的结束是内部黄色线条形成的环
所以我们可以得到,流程的数值便是最小环的边数

此时,我的第一想法便是——DFS
尝试每一个点走到底,判断是否可以形成环,同时对经过的点打标记
并且记录环的可能边数来打擂台
这样会超时3个点,70分

之后,我们来思考一下
对于每一个点最终传向的值,便是其祖先,那么如果是环的话,祖先便是自身,由此可得——并查集
对于当前点通向的下一个点,我们寻其祖先,如果形成环——祖先便是现在的点
反之,根据题意下一个点便是我们的当前点的祖先(可以看上图辅助理解)
同时环的边数也便是递归的深度
这样我们便得到了满分 (我太蒻了,为刚开始什么想不到)

但是有一点需要注意——不能路径压缩
如果路径压缩,我们在求深度时会一步到位 GG

总而言之,这题便是并查集求最小环

代码

70分DFS

#include <bits/stdc++.h>
using namespace std;

int v[200009];
int n,s,ans = INT_MAX;
bool jud[200009];
bool j;

void search(int to,int sum) {  //to是下一个,sum是当前可能的环的边数
	if (to == s) { ans = min(ans,sum); return ; }   //形成环,打擂台
	if (jud[to]) return ;   //重复走了——前面的行不通,回头
	jud[to] = true;   	//打标记
	search(v[to],sum+1);   //递进
}

int main( ) {
	scanf("%d",&n);
	for (int i = 1; i <= n; i++) scanf("%d",&v[i]);
	
	for (int i = 1; i <= n; i++) {
		memset(jud,false,sizeof(jud));   //每一次初始化
		s = i;   //确定终点
		search(v[i],1);   //开搜
	}
	
	printf("%d",ans);
	
	return 0;
}

100分并查集

#include <bits/stdc++.h>
using namespace std;

int n,ans = INT_MAX,dep;
int f[200009],v[200009];

int find(int x) {
	dep++;	
	if (x == f[x]) return x;
//	f[x] = find(f[x]);    不要路径压缩!!!
//	return f[x];
	find(f[x]);
}

int main() {
	scanf("%d",&n);
	for (int i = 1; i <= n; i++) scanf("%d",&v[i]);

	for (int i = 1; i <= n; i++) f[i] = i;   //初始化
	for (int i = 1; i <= n; i++) {
		dep = 0;   //环的边数
		if (find(v[i]) == i) ans = min(ans,dep);   //如果这是一个环,可以试试打擂台
			else
				f[i] = v[i];   //不是,下一个就是祖先
	}
	
	printf("%d",ans);
	
	return 0;
}

crx CSP-J/S RP++

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值