hdu 5148
来源:互联网 发布:ic卡发卡软件 编辑:程序博客网 时间:2024/05/19 09:51
分配城市
题目描述:
有2000个城市,是一棵树,树上的边有权值,要求选择k~50个城市,使得城市中所有两两的点的距离的总和最小.
题解:
树形dp,考虑用几个点在这棵树上,对于根节点,为了便于好写,强制要求必须选.那么如果能够搞出来,结果就是枚举所有的作为根节点然后取最小的ans,怎么搞呢?先用一种笨的方法:对于k,枚举给当前子树多少个,然后用更新值,这里有个关键点,当前u,子树v为根节点,给子树m个,那么对答案的影响是:dp[v][m]+2*m*(k-m)*边权,因为之后以一个整体数目看v,那么并不知道具体的分布,直接更新完在v树内部对答案的所有贡献. 还有更快的一点:用树形依赖背包的写法.
重点:
关键是dp[u][k]时,算出k个节点在树u上对答案的所有贡献对:就是从边的角度考虑,之后可以将他们看作一个整体
代码:
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <ctype.h>#include <limits.h>#include <cstdlib>#include <algorithm>#include <vector>#include <queue>#include <map>#include <stack>#include <set>#include <bitset>#define CLR(a) memset(a, 0, sizeof(a))#define REP(i, a, b) for(ll i = a;i < b;i++)#define REP_D(i, a, b) for(ll i = a;i <= b;i++)typedef long long ll;using namespace std;const ll maxn = 2e3 + 10;const ll INF = 1000000000000ll;ll dp[maxn][60], n, tot;struct info{ ll to, len;};vector<info> G[maxn];void dfs(ll u, ll fa){ dp[u][1] = 0;//一定会选根节点 for(ll i = 2; i <= tot; i++) { dp[u][i] = INF; } REP(i, 0, G[u].size()) { ll v = G[u][i].to, len = G[u][i].len; if(v!=fa) { dfs(v, u); for(ll j = tot; j >= 2; j--)//倒着更新 { for(ll k = 1; k <= j - 1; k++)//考虑到更新时用j-k,k不能是0,并且k不能是j,至少要留一个.不然不好用,或者之前dp[u][0]置成INF. { if(dp[u][j-k]!=INF&&dp[v][k]!=INF) dp[u][j] = min(dp[u][j], dp[u][j-k]+dp[v][k]+2ll*len*k*(tot-k)); } } } }}void solve(){ dfs(1, 0); ll ans = INF; for(ll i = 1; i <= n; i++) { ans = min(ans, dp[i][tot]);//遍历所有可能的根节点. } printf("%I64d\n", ans);}int main(){ //freopen("4Din.txt", "r", stdin); //freopen("4Dout.txt", "w", stdout); ll ncase; scanf("%I64d", &ncase); while(ncase--) { scanf("%I64d%I64d", &n, &tot); REP_D(i, 1, n) { G[i].clear(); } REP_D(i, 1, n - 1) { ll a, b, len; scanf("%I64d%I64d%I64d", &a, &b, &len); info t; t.to = b; t.len = len; G[a].push_back(t); t.to = a; G[b].push_back(t); } solve(); } return 0;}
0 0
- hdu 5148
- HDU 5148 Cities
- hdu 5148 Cities dp
- HDU 5148 Cities
- hdu
- hdu
- HDU
- hdu ()
- hdu
- hdu
- HDU
- HDU
- hdu
- hdu
- HDU
- Hdu
- hdu
- hdu-
- Java的内存溢出(OOM)
- STL学习笔记之sort算法
- QString与string类型互相转换
- Mac iTerm2快捷键
- C语言入门教程10-函数
- hdu 5148
- 更改MySQL的默认事务隔离级别
- 如何在命令行运行java文件
- LeetCode142:Linked List Cycle II
- 利用fiddler抓取Android app数据包
- 初学c++之template <typename T>
- C语言入门教程11-函数的声明定义
- Intellij IDEA默认快捷键一览
- Post和Get在http中的使用