UVA 12223 Moving to Nuremberg (树形dp)
来源:互联网 发布:东方时尚驾校网络授课 编辑:程序博客网 时间:2024/06/12 19:44
题意:
题目给出一颗n个点的树,一个人可以选择任意的位置作为开始点,然后去他喜欢的景点玩,每个景点要玩ni次,每次出去经过每个景点只能算一次,要回去之后再出来才能重新计数。但是每条边都有一个距离,现在问那些点能让他走的距离最短,出处距离和点。
题解:
这题要重根节点往子节点跟新,首先计算出最开始的根节点需要的距离,然后丛上往下跟新将起始点转移到子节点,对于某个父节点u,子节点v,如果把起始节点转移从u转到v,会产生这样的影响:v以下的节点需要走的距离会减少num[v]*w*2,v以上的节点则会增加(sum-nun[v])*w*2,w表示u-v这条边的距离,num[v]表示以v为跟的树景点的次数和,sum是总和。那么转态返程:dp[v]=dp[u]+(sum-num[v])*w*2-num[v]*w*2;
#include<iostream>#include<math.h>#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<queue>#include<map>#include<set>#define B(x) (1<<(x))using namespace std;typedef long long ll;void cmax(int& a,int b){ if(b>a)a=b; }void cmin(int& a,int b){ if(b<a)a=b; }void cmax(ll& a,ll b){ if(b>a)a=b; }void cmin(ll& a,ll b){ if(b<a)a=b; }void add(int& a,int b,int mod){ a=(a+b)%mod; }void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }const int oo=0x3f3f3f3f;const ll OO=0x3f3f3f3f3f3f3f3f;const int MOD=100007;const int maxn=50005;const int maxm=10000005;struct EDGE{ int v,w,next;}E[maxn<<1];int head[maxn],tol;ll dp[maxn];ll num[maxn],sum;int T,n,m;int u,v,w;void Init(){ memset(head,-1,sizeof head); tol=0;}void add_edge(int u,int v,int w){ E[tol].v=v; E[tol].w=w; E[tol].next=head[u]; head[u]=tol++;}int dfs(int u,int pre,int len){ dp[1]+=len*num[u]; for(int i=head[u];i!=-1;i=E[i].next){ int v=E[i].v; if(v==pre)continue; dfs(v,u,len+E[i].w*2); num[u]+=num[v]; }}void tree_dp(int u,int pre){ for(int i=head[u];i!=-1;i=E[i].next){ int v=E[i].v; if(v==pre)continue; dp[v]=dp[u]+(sum-num[v])*E[i].w*2-num[v]*E[i].w*2; tree_dp(v,u); }}void input(){ scanf("%d",&n); for(int i=1;i<n;i++){ scanf("%d %d %d",&u,&v,&w); add_edge(u,v,w); add_edge(v,u,w); } memset(num,0,sizeof num); scanf("%d",&m); sum=0; for(int i=1;i<=m;i++){ scanf("%d %d",&u,&w); num[u]=w; sum+=w; } dp[1]=0;}void solve(){ ll ans=OO; for(int i=1;i<=n;i++) cmin(ans,dp[i]); cout<<ans<<endl; int f=0; for(int i=1;i<=n;i++){ if(dp[i]==ans){ if(f++) printf(" "); printf("%d",i); } } puts("");}int main(){ //freopen("E:\\read.txt","r",stdin); scanf("%d",&T); while(T--){ Init(); input(); dfs(1,-1,0); tree_dp(1,-1); solve(); } return 0;}
0 0
- 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)
- uva 12223 - Moving to Nuremberg
- uva12223 - Moving to Nuremberg 树形DP
- UVALive - 4614 Moving to Nuremberg (树形DP)
- UVALive - 4614 Moving to Nuremberg (树形DP)
- UVALive 4614 Moving to Nuremberg(树形DP)
- Moving to Nuremberg - POJ 3847 dp
- UVALive 4614 Moving to Nuremberg
- UVALive 4614 Moving to Nuremberg
- POJ - 3847 Moving to Nuremberg 动归
- uva 12223(树形dp)
- uva 10859 树形dp
- uva 1292(树形dp)
- uva 1407(树形dp)
- 防止页面缓存
- Android Studio 简单介绍和使用问题小结
- HTML5 LocalStorage 本地存储
- 【转自www.dbafan.com】消失的segment
- 反汇编学习之路之静态数据成员
- UVA 12223 Moving to Nuremberg (树形dp)
- kendo 验证控件 按指定 信息 提示
- 关于eclipse背景全部设置为豆沙绿色的小技巧
- opengl 渲染流程
- Android 表单验证开源框架 saripaar
- php读取TXT文件(带换行、缩进)
- IO流之FileInputStream和FileOutputStream
- Android中屏蔽 电源键长按、Home键、Home长按
- MyEclipse一站式调试Maven Web项目