求证为什么本题贪心思路是假的
查看原帖
求证为什么本题贪心思路是假的
373938
wowwowwow楼主2024/10/11 19:02

刚看到这道题的时候想到了一个用优先队列的贪心思路,大致是统计每个点用魔法消除的贡献,每次删除贡献最大的,删除过程中维护每个点贡献。我觉得蛮对的但是结果甚至过不了样例。

code:

#include<bits/stdc++.h>
#define int long long
#define mk make_pair
using namespace std;

const int N = 2e3 + 7;
int T, n, fa[N], hp[N], sum[N];
vector<int> g[N];

void solve() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) g[i].clear(), sum[i] = 0;
	for(int i = 2; i <= n; i++) {
		scanf("%d", &fa[i]);
		g[fa[i]].push_back(i);
	}
	for(int i = 1; i <= n; i++) 
		scanf("%d", &hp[i]);
	int ans = 0;
	priority_queue<pair<int, int> > q, del;
	for(int i = 1; i <= n; i++) {
		sum[i] = hp[i];
		if(i != 1) sum[i] += hp[i];
		ans += hp[i];
		for(int v : g[i]) {
			sum[i] += hp[v]; ans += hp[v];
		}
		q.push(mk(sum[i], i));
	}
	printf("%lld ", ans);
	for(int m = 1; m <= n; m++) {
		while(!del.empty() && !q.empty() && del.top() == q.top()) {
			del.pop(); q.pop();
		}
		int delt = q.top().first, u = q.top().second; q.pop();
		ans -= delt; sum[u] = 0;
		printf("%lld", ans); if(m != n) printf(" ");
		if(u != 1 && sum[fa[u]] != 0) {
			del.push(mk(sum[fa[u]], fa[u]));
			sum[fa[u]] -= hp[u];
			q.push(mk(sum[fa[u]], fa[u]));
		} 
		for(int v : g[u]) {
			if(sum[v] != 0) {
					
				del.push(mk(sum[v], v));
				sum[v] -= hp[v];
				q.push(mk(sum[v], v));
			}
		}
	}
	printf("\n");
//	dfs(1);
}

signed main() {
	scanf("%d", &T);
	while(T --) {
		solve();
	}
	return 0;
} 

不是很明白为什么错。求大佬解答。

2024/10/11 19:02
加载中...