uva 12223 - Moving to Nuremberg
来源:互联网 发布:淘宝卖家说加微信返现 编辑:程序博客网 时间:2024/06/05 21:02
Moving to Nuremberg
题目描述:
给出n,表示有n个位置,n个位置有n-1条边,形成一个无根的树,每条边上都有权值。现在每个位置都有一个景点,一个人想在一年之内去ki次景点,所以接下来给出m,表示说在m个位置上有这个人想去的地方,给出位置以及想去的次数(注意,每去一个景点都要返回自己的住处),然后问说,这个人该住在哪里走的路程才最短。
题解:
常用的一种简单的树上枚举根的转移方法.第一次以1为根树形dp,搞出以u为根的到1的总距离.然后开始在树上转移.如果有fa的结果,怎么算出u的结果?本题并不需要改dp值,并且改dp值需要改的东西太多.直接算就行了,因为u的儿子的总有效个数知道了,那么就是减少了这么多,增加了剩下那么多的2*fa_u_len,就得到结果了.因此dp也不要放对答案的贡献了,直接放个数就好…
重点:
树形dp+在树上枚举根节点进行快速转移
代码:
#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 = 50000 + 100;ll n, num[maxn], c[maxn], dp[maxn];//其实dp不用也行,主要是num和之后计算出1为根,之后再转移根struct info{ ll to, len, next;};info edge[maxn*2 +1];ll sum;ll tot, head[maxn];ll ans;ll ans_i[maxn], now;void add_edge(ll a, ll b, ll len){ edge[tot].to = b; edge[tot].len = len; edge[tot].next = head[a]; head[a] = tot; tot++; edge[tot].to = a; edge[tot].len = len; edge[tot].next = head[b]; head[b] = tot; tot++;}void dfs_num(ll u, ll fa){ num[u] = c[u]; for(ll i = head[u]; i!=-1; i = edge[i].next) { ll v = edge[i].to, len = edge[i].len; if(v!=fa) { dfs_num(v, u); num[u] += num[v]; } }}void dfs_first(ll u, ll fa, ll road){ dp[1] += (c[u]*road*2); for(ll i = head[u]; i!=-1; i = edge[i].next) { ll v = edge[i].to, len = edge[i].len; if(v!=fa) { dfs_first(v, u, road+len); } }}void dfs(ll u, ll fa, ll fa_ans, ll fa_len){ if(fa==0) { for(ll i = head[u]; i!=-1; i = edge[i].next) { ll v = edge[i].to, len = edge[i].len; if(v!=fa) { dfs(v, u, dp[u], len); } } } else { dp[u] = fa_ans; dp[u] -= 2*fa_len*num[u]; dp[u] += 2*fa_len*(sum-num[u]); for(ll i = head[u]; i!=-1; i = edge[i].next) { ll v = edge[i].to, len = edge[i].len; if(v!=fa) { dfs(v, u, dp[u], len); } } }}void solve(){ dfs_num(1, 0); dp[1] = 0; dfs_first(1, 0, 0); dfs(1, 0, 0, 0); ans = 10000000000000000ll; now = 0; REP_D(i, 1, n) { if(dp[i] < ans) { ans = dp[i]; now = 0; ans_i[now] = i; now++; } else if(dp[i]==ans) { ans_i[now] = i; now++; } } sort(ans_i, ans_i + now); printf("%lld\n", ans); REP(i, 0, now) { printf("%lld%c", ans_i[i], (i==now-1 ? '\n' : ' ')); }}int main(){ //freopen("8Hin.txt", "r", stdin); //freopen("8Hout.txt", "w", stdout); int ncase; scanf("%d", &ncase); while(ncase--) { scanf("%lld", &n); memset(head, -1, sizeof(head)); tot = 0; //CLR(num); sum = 0; CLR(c); REP_D(i, 1, n - 1) { ll a, b, len; scanf("%lld%lld%lld", &a, &b, &len); add_edge(a, b, len); } ll t; scanf("%lld", &t); while(t--) { ll a, b; scanf("%lld%lld", &a, &b); c[a] += b; sum += b; } solve(); } return 0;}
0 0
- uva 12223 - Moving to Nuremberg
- UVA 12223 Moving to Nuremberg (树形dp)
- UVA 12223 - Moving to Nuremberg(树形DP)
- uva 12223 - Moving to Nuremberg(树形dp)
- UVA 12223 Moving to Nuremberg(树形DP)
- Uva 12223 Moving to Nuremberg(树形dp)
- UVALive 4614 Moving to Nuremberg
- UVALive 4614 Moving to Nuremberg
- Moving to Nuremberg - POJ 3847 dp
- uva12223 - Moving to Nuremberg 树形DP
- POJ - 3847 Moving to Nuremberg 动归
- UVALive - 4614 Moving to Nuremberg (树形DP)
- UVALive - 4614 Moving to Nuremberg (树形DP)
- UVALive 4614 Moving to Nuremberg(树形DP)
- UVA - 1533 Moving Pegs
- UVA - 1533 (Moving Pegs)
- UVA 12569 Moving Pegs
- Moving Pegs UVA
- genymotion完整配置
- 公司找人写一个软件 有酬劳
- 蛇行亿年炮上限99,改为100
- 函数式编程初探
- Python set模块使用方法
- uva 12223 - Moving to Nuremberg
- SQL Server 数据库最小宕机迁移方案
- python中if __name__ == '__main__': 的解析
- 【转】深圳的NB公司-四华一启
- 使用ANT打包Android应用
- leetcode Implement strStr()
- 中科院计算所培训中心三季度公开课安排
- 天声人語 20150608
- [leetcode] Single Number