关于假作法
查看原帖
关于假作法
98096
Smallbasic楼主2022/12/31 11:45

luogu上能过,但是LOJ上只有85分,请问是wqs二分的问题还是dp(f[i][0/1/2]f[i][0/1/2] 表示 ii 下面连了 0/1/20/1/2 条边)的问题?正确做法是什么啊qwq

#include <bits/stdc++.h>

using namespace std;

const int N = 3e5 + 5;

typedef long long ll;

const ll inf = 1e18;

ll C = 0;

struct node {
	ll v; int k;
	inline node(ll V, int K) : v(V), k(K) { }
	inline node() { v = -1e18; k = 0; }
	inline bool operator > (const node &b) const { return v + C * k == b.v + C * b.k ? k < b.k : v + C * k > b.v + C * b.k; }
	inline bool operator < (const node &b) const { return v + C * k == b.v + C * b.k ? k > b.k : v + C * k < b.v + C * b.k; }
};

inline node operator + (node a, node b) { return node(a.v + b.v, a.k + b.k); }
inline node operator - (node a, node b) { return node(a.v - b.v, a.k - b.k); }

template<typename T> inline T max_(T a, T b) { return a > b ? a : b; } 

node f[N][3];

struct edge {
	int head, to, nxt, val;
} ed[N << 1];

int en = 0;

inline void addedge(int from, int to, int val) {
	ed[++en].to = to; ed[en].val = val; ed[en].nxt = ed[from].head; ed[from].head = en;
}

inline void dfs(int now, int fa) {
	f[now][0] = node(0, 0);
	f[now][1] = node(-inf, 0);
	f[now][2] = node(0, 1);
	for (int i = ed[now].head; i; i = ed[i].nxt) {
		int v = ed[i].to;
		if (v == fa) continue;
		dfs(v, now);
		node tmp;
		tmp = f[now][2];
		for (int j = 0; j < 3; ++j) f[now][2] = max_(f[now][2], tmp + f[v][j]);
		f[now][2] = max_(f[now][2], f[now][1] + f[v][0] + node(ed[i].val, 0));
		f[now][2] = max_(f[now][2], f[now][1] + f[v][1] + node(ed[i].val, -1));
		tmp = f[now][1];
		for (int j = 0; j < 3; ++j) f[now][1] = max_(f[now][1], tmp + f[v][j]);
		f[now][1] = max_(f[now][1], f[now][0] + f[v][0] + node(ed[i].val, 1));
		f[now][1] = max_(f[now][1], f[now][0] + f[v][1] + node(ed[i].val, 0));
		tmp = f[now][0];
		for (int j = 0; j < 3; ++j) f[now][0] = max_(f[now][0], tmp + f[v][j]);
	}
}

inline int read() {
	register int s = 0, f = 1; register char ch = getchar();
	while (!isdigit(ch)) f = (ch == '-' ? -1 : 1), ch = getchar();
	while (isdigit(ch)) s = (s * 10) + (ch & 15), ch = getchar();
	return s * f;
}

int n, k;

int main() {
	n = read(); k = read(); ++k;
	for (int i = 1, u, v, w; i < n; ++i) {
		u = read(); v = read(); w = read();
		addedge(u, v, w); addedge(v, u, w);
	} ll L = -1e12, R = 1e12;
	while (L <= R) {
		C = (L + R + inf) / 2ll - inf / 2ll;
		dfs(1, 0); node p = max_(f[1][0], max_(f[1][1], f[1][2]));
		if (p.k == k) {
			printf("%lld\n", p.v);
			return 0;
		}
		if (p.k < k) L = C + 1;
		else R = C - 1;
	} dfs(1, 0); node p = max_(f[1][0], max_(f[1][1], f[1][2]));
	printf("%lld\n", p.v);
	return 0;
}
2022/12/31 11:45
加载中...