Codeforces 61D--树形dp

自己画个图就会发现如果从起点到终点直接是一条边的话那么直接累加weight即可,然后有可能起点在中间,先向一边走再向另一边走,这样就导致了会把一些边走两次,【记做重复边】,回到起点后,可以直达终点【直达边】,只有这两种边,那么显然这两部分权值累加即可,故答案可以化为:2*总权值-直达边权值之和。【建议自己画图模拟】是一个基础的树形dp。


A题

我本来想切完囧爷这个专题在写的,但是不想保存代码,所以一个一个发了。

专题链接:点击打开链接


Code:

/****************************************
* author:crazy_石头
* pro:Codeforces 61D
* date:2014/04/15
* algorithm: Tree Dp
*****************************************/ 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define INF INT_MAX
#define eps 1e-8
#define A system("pause")
#define rep(i,h,n) for(int i=(h);i<=(n);i++)
#define ms(a,b) memset((a),(b),sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define mod 1e9+7
#define LL long long
const int maxn=1e5+5;

struct edge
{
    int to,next,w;
}e[maxn<<2];
int head[maxn],cnt;

inline void add(int u,int v,int w)
{
    e[cnt].to=v;
    e[cnt].next=head[u];
    e[cnt].w=w;
    head[u]=cnt++;
}

inline LL dfs(int u,int f,int value)
{
    LL ret=value;
    for(int i=head[u];~i;i=e[i].next)
    {
          int v=e[i].to,w=e[i].w;
          if(v!=f) ret=std::max(ret,dfs(v,u,value+w));
    }
    return ret;
}  

inline void init()
{
    ms(head,-1),cnt=0;
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        init();
        int a,b,w;
        LL ret=0;
        rep(i,1,n-1)
        {
           scanf("%d%d%d",&a,&b,&w);
           ret+=w;
           add(a,b,w);
           add(b,a,w);
        }
        int ans=dfs(1,0,0);
        printf("%lld\n",2*ret-ans);
    }
    //A;
    return 0;
}
        

你可能感兴趣的:(ACM_dp)