HDU 6769 In Search of Gold 二分答案+树形DP
Posted kaka0010
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6769 In Search of Gold 二分答案+树形DP相关的知识,希望对你有一定的参考价值。
原题链接:https://acm.hdu.edu.cn/showproblem.php?pid=6769
题意
有一棵树,每条边都有两个权值a,b可以选择,一共可以选择k条a权值,n-1-k条b权值,问最小的树的直径是多少?
分析
非常好的一道题,可以让人基本上弄懂树形背包的复杂度。
先考虑状态,根据套路容易写出 f [ u ] [ j ] f[u][j] f[u][j]代表u节点选择j条a权值的边到最远叶子结点距离的最小值,这样状态转移就可以轻松推出
f [ u ] [ i + j + 1 ] = m i n ( f [ u ] [ i + j + 1 ] , f [ u ] [ i ] , f [ v ] [ j ] + a ) f[u][i+j+1]=min(f[u][i+j+1], f[u][i], f[v][j]+a) f[u][i+j+1]=min(f[u][i+j+1],f[u][i],f[v][j]+a)
f [ u ] [ i + j ] = m i n ( f [ u ] [ i + j ] , f [ u ] [ i ] , f [ v ] [ j ] + b ) f[u][i+j]=min(f[u][i+j], f[u][i], f[v][j]+b) f[u][i+j]=min(f[u][i+j],f[u][i],f[v][j]+b)
此时还是存一个 t m p [ j ] tmp[j] tmp[j]来暂时表示当前层的转移,这样不会造成dp反复更新,而且复杂度也是NK的。
接着我们怎么和直径扯上关系呢,如果想直接靠这个转移得到最小直径是不行的,状态还不够表示,因此考虑二分答案,我们直接在合并时判断当前最长链是否超过mid,如果超过则不合并答案,最后检查根节点的最长链长度是否超过mid,答案是满足单调性的。
总时间复杂度也就是 O ( N K l o g A n s ) O(NKlogAns) O(NKlogAns)
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int ul;
typedef pair<int, int> PII;
const int inf = 0x3f3f3f3f;
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const ll mod = 1e9 + 7;
const double eps = 1e-8;
#define lowbit(i) (i & -i)
#define Debug(x) cout << (x) << endl
#define fi first
#define se second
#define mem memset
#define endl '\\n'
namespace StandardIO {
template<typename T>
inline void read(T &x) {
x = 0; T f = 1;
char c = getchar();
for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
for (; c >= '0' && c <= '9'; c = getchar()) x = x * 10 + c - '0';
x *= f;
}
template<typename T>
inline void write(T x) {
if (x < 0) putchar('-'), x *= -1;
if (x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
}
using namespace StandardIO;
int n, k, h[N], cnt;
struct Edge {
int to, next, a, b;
}e[N];
void add(int u, int v, int a, int b) {
e[cnt].to = v;
e[cnt].a = a;
e[cnt].b = b;
e[cnt].next = h[u];
h[u] = cnt++;
}
ll f[N][25], tmp[25];
int siz[N];
void dfs(int x, int fa, ll len) {
siz[x] = 0;
for (int i = 0; i <= k; i++) f[x][i] = 0;
for (int i = h[x]; ~i; i = e[i].next) {
int v = e[i].to;
if (v == fa) continue;
dfs(v, x, len);
int K = min(siz[x] + siz[v] + 1, k);
for (int j = 0; j <= K; j++) tmp[j] = len + 1;
for (int j = 0; j <= min(siz[x], K); j++) {
for (int l = 0; l <= siz[v] && j + l <= K; l++) {
if (f[x][j] + f[v][l] + e[i].a <= len) {
tmp[j + l + 1] = min(tmp[j + l + 1], max(f[x][j], f[v][l] + e[i].a));
}
if (f[x][j] + f[v][l] + e[i].b <= len) {
tmp[j + l] = min(tmp[j + l], max(f[x][j], f[v][l] + e[i].b));
}
}
}
for (int j = 0; j <= K; j++) f[x][j] = tmp[j];
siz[x] += siz[v] + 1;
}
}
inline void solve() {
int T; read(T); while (T--) {
read(n), read(k);
for (int i = 0; i <= n; i++) h[i] = -1;
cnt = 0;
ll r = 0, l = 1;
for (int i = 1; i <= n - 1; i++) {
int u, v, a, b;
read(u), read(v), read(a), read(b);
add(u, v, a, b);
add(v, u, a, b);
r += max(a, b);
}
while (l <= r) {
ll mid = (l + r) >> 1;
dfs(1, 0, mid);
if (f[1][k] <= mid) r = mid - 1;
else l = mid + 1;
}
printf("%lld\\n", l);
}
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug = 0;
do {
if (acm_local_for_debug == '$') exit(0);
if (test_index_for_debug > 20)
throw runtime_error("Check the stdin!!!");
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
solve();
#endif
return 0;
}
以上是关于HDU 6769 In Search of Gold 二分答案+树形DP的主要内容,如果未能解决你的问题,请参考以下文章
Application of Breath-first search in AI(route search)
Application of Breath-first search in AI(route search)
LeetCode 702. Search in a Sorted Array of Unknown Size