AC日记——Two poj 1849

Two

思路:

  树形DP求直径;

  答案是边权总和*2-直径;

  dp[i][1]::以i为根的子树中最长的路径;

  dp[i][0]::以i为根的子树中次长的路径;

来,上代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 100005

int n,s,E[maxn<<1],V[maxn<<1],W[maxn<<1],cnt;
int head[maxn],dp[maxn][2],sum,ans=0;

inline void in(int &now)
{
    char Cget=getchar();now=0;
    while(Cget>'9'||Cget<'0') Cget=getchar();
    while(Cget>='0'&&Cget<='9')
    {
        now=now*10+Cget-'0';
        Cget=getchar();
    }
}

void dfs(int now,int fa)
{
    bool res=true;
    int pos=0,gs=0;
    for(int i=head[now];i;i=E[i])
    {
        if(V[i]==fa) continue;
        res=false,dfs(V[i],now);
        if(W[i]+dp[V[i]][0]>gs) gs=W[i]+dp[V[i]][0],pos=V[i];
    }
    if(res) return ;
    dp[now][0]=gs,gs=0;
    for(int i=head[now];i;i=E[i])
    {
        if(V[i]==fa||V[i]==pos) continue;
        if(W[i]+dp[V[i]][0]>gs) gs=W[i]+dp[V[i]][0];
    }
    dp[now][1]=gs,ans=max(ans,dp[now][1]+dp[now][0]);
}

int main()
{
    in(n),in(s);int u,v,w;
    for(int i=1;i<n;i++)
    {
        in(u),in(v),in(w),sum+=w*2;
        E[++cnt]=head[u],V[cnt]=v,W[cnt]=w,head[u]=cnt;
        E[++cnt]=head[v],V[cnt]=u,W[cnt]=w,head[v]=cnt;
    }
    dfs(s,0);
    cout<<sum-ans;
    return 0;
}
原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6783168.html