codeforces 61D Eternal Victory 树形DP

来源:互联网 发布:mysql开启日志功能 编辑:程序博客网 时间:2024/04/30 12:10

题意:以一棵树的1节点为起点,某点为终点,遍历所有节点。选择适当的终点求出最短的旅游距离。

做法:基本的树形DP,求出每颗子树所有边的和,模拟一下,就可以得出f(u)=f(father)-2*sum[u]-2*line(u,v)+line(u,v)+sum[u]*2;

当然,父节点是0的时候着重考虑一下。

#include <iostream>#include <map>#include <vector>#include <utility>#include <cstdio>#define LMT 100003#define LL long long//单点的时候啊,ans输出不可为-1!!using namespace std;LL sum[LMT],tem[LMT],ans;map<pair<int,int>,LL>line;vector<int>gra[LMT];void inidfs(int u,int pri){    for(size_t i=0;i<gra[u].size();i++)    if(gra[u][i]!=pri)    {        int v=gra[u][i];inidfs(v,u);        sum[u]+=line[make_pair(u,v)]+sum[v];    }}void dfs(int u,int pri){    if(pri!=-1)    {        LL add;        if(pri!=1)add=tem[pri]-2*sum[u]-2*line[make_pair(pri,u)];        else add=2*(sum[pri]-sum[u]-line[make_pair(pri,u)]);        tem[u]=add+line[make_pair(pri,u)]+sum[u]*2;        if(ans==-1||ans>tem[u])ans=tem[u];    }    for(size_t i=0;i<gra[u].size();i++)    if(gra[u][i]!=pri)    {        int v=gra[u][i];        dfs(v,u);    }}int main(){    int n,u,v;    LL w;    scanf("%d",&n);ans=-1;    for(int i=1;i<n;i++)    {        scanf("%d%d%I64d",&u,&v,&w);        line[make_pair(u,v)]=w;        line[make_pair(v,u)]=w;        gra[u].push_back(v);        gra[v].push_back(u);    }    inidfs(1,-1);    tem[1]=sum[1];    dfs(1,-1);    ans=ans<0?0:ans;    printf("%I64d\n",ans);    return 0;}


原创粉丝点击