PAT顶级 1021 Safe Fruit (35分)(Bron-Kerbosch求最大团)

欢迎大家访问我的PAT TOP解题目录~

https://blog.csdn.net/qq_45228537/article/details/103671868

题目链接:

1021 Safe Fruit (35分)

思路:

首先跟这位巨巨学了最大团Bron-Kerbosch算法:https://www.cnblogs.com/yefeng1627/archive/2013/03/31/2991592.html
然后参考了这位巨巨的题解:https://blog.csdn.net/qq_41562704/article/details/103377879,注意到了题目给出的N个映射关系里出现过的水果,篮子里可能没有
学会最大团之后就会发现,题目给的图的补图的最大团就是本题的解了(当然相同数量还需要比较一下价格);

代码:

#include<bits/stdc++.h>

using namespace std;

const int maxn = 1005;
int no[maxn], id[maxn];
int n, res, cost;
int G[maxn][maxn], cnt[maxn], group[maxn], vis[maxn], p[maxn];

void dfs(int u, int ans, int t_cost){
	for(int i = u + 1; i <= n; i++){
		if(cnt[i] + ans < res || (cnt[i] + ans == res && t_cost >= cost)) return;
		if(G[u][i]){
			for(int j = 0; j < ans; j++) if(!G[i][vis[j]]) goto skip;
			vis[ans] = i;
			dfs(i, ans + 1, t_cost + p[i]);
			skip:;
		}
	}
	if(ans > res || (ans == res && t_cost < cost)){
		for(int i = 0; i < ans; i++) group[i] = vis[i];
		res = ans;
		cost = t_cost;
	}
}
void maxclique(){
	res = -1;
	for(int i = n; i; i--){
		vis[0] = i;
		dfs(i, 1, p[i]);
		cnt[i] = res;
	}
}

int main() {
#ifdef MyTest
	freopen("Sakura.txt", "r", stdin);
#endif	
	int k, pos = 1;
	scanf("%d %d", &k, &n);
	memset(G, -1, sizeof(G));
	vector<pair<int, int> > rcd(k);
	for(int i = 0; i < k; i++) scanf("%d %d", &rcd[i].first, &rcd[i].second);
	for(int i = 0; i < n; i++){
		int x, pr;
		scanf("%d %d", &x, &pr);
		if(!no[x]) no[x] = pos, id[pos++] = x;	
		p[no[x]] = pr;
	}
	for(pair<int,int> & x : rcd) G[no[x.first]][no[x.second]] = G[no[x.second]][no[x.first]] = 0;
	maxclique();
	vector<int> v;
	for(int i = 0; i < res; i++) v.push_back(id[group[i]]);
	sort(v.begin(), v.end());
	printf("%d\n%03d", res, v[0]);
	for(int i = 1; i< res; i++) printf(" %03d", v[i]);
	printf("\n%d", cost);
	return 0;
}
posted @ 2020-01-09 19:46  YuhanのBlog  阅读(615)  评论(0编辑  收藏  举报