6.26模拟赛(1)总结(T1:信息传递;T2:传染病控制;T3:排列;T4:最大数)

16:33:56

2020-06-26

当然可以先看一下成绩:

非常显然的成绩不能算有多好,当然其实这也可能是假期水课的报应  (额)

但是比我集训前想象的要好一点(集训时想象的是排名前30就可以,嗯?

好了,毕竟是第一天,后面日子还长,相信结果不会烂的。

好了,现在看一下第一题:

第一题

  原题来自洛谷P2661 :题目链接:https://www.luogu.com.cn/problem/P2661

比较显然的暴力思路(就是我写的)但是复杂度是O(n2)的,显然只有60分。

然后想正解,比较显然想到求一个最小环。但是如何求?

仔细观察这道题可以发现 每人只会把信息告诉一个人,也就是说只有一条出边

然后可以显然的发现图里只有简单环,那么我们可以想到求Tarjan强连通分量。

就是个裸板子,下面是代码:(注意只是这道题比较特殊,才能用Tarjan水过)

#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=200005;
int a[maxn];
int Min=9999999;
int dfn[maxn],low[maxn],dfs_clock,sta[maxn],top,belong[maxn],siz[maxn],dcc;
void tarjan(int u){
	dfn[u]=low[u]=++dfs_clock;
	sta[++top]=u;
	int v=a[u];
	if(!dfn[v]){
		tarjan(v);
		low[u]=min(low[u],low[v]);
	}
	else if(!belong[v])low[u]=min(low[u],dfn[v]);
	if(dfn[u]==low[u]){
		dcc++;
		while(1){
			int x=sta[top--];
			belong[x]=dcc;
			siz[dcc]++;
			if(x==u)break;
		}
		if(siz[dcc]!=1) Min=min(siz[dcc],Min);
	}
}
int main(){
	//freopen("a.in","r",stdin);
	int n;scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=n;i++){
		if(!dfn[i])tarjan(i);
	}
	printf("%d",Min);
	return 0;
}

  

但是就这样水过肯定是不行的,那么还有没有其他解法呢?

显然是有的。但是不大好理解,等过会再加。

 第二题

 

这道题当时我是看错题意了,所以想成了树形DP,但成功水了三十分。

其实这道题没有正解,一般人都能想到贪心,但是贪心总是不能AC(80pts

其实吧,不要想南么复杂,其实数据范围才300 ,直接爆搜(加一小小优化)就能过,

但是代码比较不大好写(本人目前还没有成功写出

所以代码暂时不给了,先说一下思路:

首先dfs 一遍 求出 deep深度,size 子树大小,和father父亲。

然后依次每一深度枚举切断的边就行了。

代码到时会给的(会加一些注释)。。。。。。

 

猜你喜欢

转载自www.cnblogs.com/DZN2004/p/13195419.html