题目大意:给出n,一个无根的树,每条边上都有权值。
现在每个位置都有一个景点,一个人想在一年之内去cnt[ i ] 次景点,所以接下来给出m,表示说在m个位置上有这个人想去的地方,给出位置以及想去的次数(注意,每去一个景点都要返回自己的住处),namo这个人该住在哪里走的路程才最短。
换根dp
#include <iostream> #include <algorithm> #include <cstring> using namespace std; const int N =1e5,M=N; #define int long long const int inf =1e9 ; int n,m,f[N],g[N],s[N] ; int ans ; int nxt[M],go[M],hd[N],all=1,w[M]; void add_(int x,int y,int z){ all++;go[all]=y; nxt[all]=hd[x]; hd[x]=all; w[all]=z; } void clr() { ans=inf; memset(s, 0, sizeof s); all=1; for (int i= 0;i<=n; i++) hd[i]=0; } void dfs(int x,int fa){ f[x]=0; for(int i=hd[x];i;i=nxt[i]){ int y=go[i],z=w[i]; if(fa==y) continue; dfs(y,x); s[x]+=s[y]; f[x]+=f[y]+2*z*s[y] ; } } void dp(int x,int fa){ ans=min(ans,g[x]); for(int i=hd[x];i;i=nxt[i]){ int y=go[i],z=w[i]; if(fa==y) continue; g[y]= g[x]- s[y]*2*z + (s[1]-s[y])*2*z; dp(y,x); } } signed main(){ int tes;cin>>tes; while(tes--){ cin>>n; clr(); int x,y,z; for(int i=1;i<n;i++) cin>>x>>y>>z,add_(x,y,z),add_(y,x,z); cin>>m; for(int i=1;i<=m;i++) cin>>x>>z,s[x]=z; dfs(1,0); g[1]=f[1]; ans=g[1]; dp(1,0); cout<<ans <<endl; int flg = 0; for (int i=1;i<=n;i++) { if (g[i] ==ans && !flg) { cout<<i; flg = 1; } else if (g[i] ==ans) cout<<' '<<i; } cout<<endl; } }
标签:Nuremberg,景点,int,add,Moving,UVA12223,ans,include,hd From: https://www.cnblogs.com/towboa/p/17352301.html