luogu P4212 外太空旅行

luogu P4212 外太空旅行

题解为什么都是随机化或bitset的呀

这题明明就是最大团板子题啊

是不是对最大团问题有什么误解

搜索加3个剪枝没有压力跑过去了呀

没开O2 : https://www.luogu.org/record/24996441

开O2 : https://www.luogu.org/record/24995977

首先讲讲怎么搜索吧

我们可以考虑设立 F(i),表示只考虑标号 ≥ i 的点所能构成的最大团的点数

那么我们就可以从 n 到 1 依次枚举,假设枚举到 i 号点,我们可以钦定强制选择 i 号点作为团中的点,然后从小到大依次枚举 i 号点所连向的编号大于 i 的点,选为团中的点,然后不断进行这样的操作,注意要保证当前选的点要和之前选的点都有连边才合法。

注意 F(i) ≤ F(i+1) + 1,因为我每次只添加一个点,不可能把最大团的点数加2。所以如果把 F(i) 更新为了 F(i+1) + 1,那么就可以直接退出。(最优性剪枝 1)

扫描二维码关注公众号,回复: 10019701 查看本文章

如果当前深度是 depth,最后一个枚举的点是 u,设 D(u) 为编号大于 u 的且与u 有连边的点的个数,那么如果 depth + D(u) ≤ F(i),那么这之后也肯定不可能会有更优的解,直接退出。(最优性剪枝 2)

假设当前深度是 depth,最后一个枚举的点是 u,如果 depth + F(u+1) ≤ F(i),那么这之后肯定不可能会有更优的解,直接退出。(最优性剪枝 3)

code:

#include<bits/stdc++.h>
#define N 55
using namespace std;
int n, ans, g[N][N], S[N][N], f[N];
void dfs(int m, int dep) {
	if(dep > ans) {//最优性剪枝 1
		ans = dep;
		return;	
	}
	for(int i = 1; i <= m; i ++) {
		if(dep + m - i + 1 <= ans) continue;//最优性剪枝 2
		if(dep + f[S[dep][i]] <= ans) continue;//最优性剪枝 3
		int sz = 0;
		for(int j = i + 1; j <= m; j ++)
			if(g[S[dep][i]][S[dep][j]]) S[dep + 1][++ sz] = S[dep][j];
		dfs(sz, dep + 1);
	}
}
int main() {
	scanf("%d", &n);
	int u, v;
	while(~scanf("%d%d", &u, &v)) g[u][v] = g[v][u] = 1;//这里题面就不能强调一下吗? 
	
	for(int i = n; i >= 1; i --) {
		int m = 0;
		for(int j = i + 1; j <= n; j ++) 	
			if(g[i][j]) S[1][++ m] = j;
		dfs(m, 1);
		f[i] = ans;
	}
	printf("%d", ans);
	return 0;
}

发布了157 篇原创文章 · 获赞 90 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_38944163/article/details/102480046