求助!连珠线这个题这样做为什么错了
  • 板块学术版
  • 楼主YingLi
  • 当前回复3
  • 已保存回复3
  • 发布时间2021/3/27 07:42
  • 上次更新2023/11/5 01:34:08
查看原帖
求助!连珠线这个题这样做为什么错了
116824
YingLi楼主2021/3/27 07:42

我有一个思路是这样的:考虑dp[u][0/1]表示当前点是否作为祖先关系的两段蓝边的中点。蓝边只有两种形态,一种是祖先关系的直链,一种是折过来。因为一个点如果作为直链蓝边的中点,那就只能过这一次;不作为中点的话可以随便挂直链,也可以挂一个折链,但是折链只能挂一个。

于是我考虑转移:首先不考虑折链的话,dp[u][0]=vson[u]max(dp[v][0],dp[v][1]+e[i].w)dp[u][0]=\sum_{v \in son[u]}max(dp[v][0], dp[v][1]+e[i].w)。 考虑直链就相当于选一个儿子强行作为蓝线的一头,也就是选一个儿子从max(dp[v][0],dp[v][1]+e[i].w)max(dp[v][0], dp[v][1]+e[i].w)换成dp[v][0]+e[i].wdp[v][0]+e[i].w,其余的儿子不变;考虑折链就相当于是选两个儿子这样替换,所以找一个d[v][0]+e[i].wmax(dp[v][0],dp[v][1]+e[i].w)d[v][0]+e[i].w-max(dp[v][0], dp[v][1]+e[i].w)的最大值和次大值替换下来就行了。

然后就WA得只有20分QwQ有大佬可以指出一下这样dp哪里错了吗。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define maxn 200005
using namespace std;
typedef long long ll;
int read() {
	int x = 0, f = 1, ch = getchar();
	while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
	while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
	return x * f;
}

struct edge {int to, w, nxt;} e[maxn << 1];
int head[maxn], k = 0;
void add(int u, int v, int w) {e[k] = {v, w, head[u]}; head[u] = k++;}

int n, f[maxn][2], fa[maxn];
void dfs(int u) {
	bool flag = false; int tmp, mx = -(0x3f3f3f3f), mx2 = -(0x3f3f3f3f);
	f[u][1] = -(0x3f3f3f3f), f[u][0] = 0; 
	for(int i = head[u]; ~i; i = e[i].nxt) {
		register int v = e[i].to; if(v == fa[u]) continue;
		flag = true;
		fa[v] = u; dfs(v);
		tmp = max(f[v][0], f[v][1] + e[i].w);
		f[u][0] += tmp;
		f[u][1] = max(f[u][1], f[v][0] + e[i].w - tmp);
		tmp = f[v][0] + e[i].w - tmp;
		if(tmp >= mx) mx2 = mx, mx = tmp;
		else if(tmp >= mx2) mx2 = tmp;
	}
	f[u][1] += f[u][0]; if(mx + mx2 > 0) f[u][0] += mx + mx2;
}

signed main() {
	memset(head, -1, sizeof head);
	n = read();
	for(int i = 1, u, v, w; i < n; i++) u = read(), v = read(), w = read(), add(u, v, w), add(v, u, w);
	
	dfs(1);
	printf("%d\n", f[1][0]);
	return 0;
}
2021/3/27 07:42
加载中...