小A与欧拉路 (求树的最长路)

题目描述 

小A给你了一棵树,对于这棵树上的每一条边,你都可以将它复制任意(可以为0)次(即在这条边连接的两个点之间再加一条边权相同的边),求所有可能新形成的图中欧拉路的最短长度

欧拉路:从图中任意一个点开始到图中任意一个点结束的路径,并且图中每条边只通过恰好一次

输入描述:

第一行一个数 n ,表示节点个数

接下来 n-1 行,每行三个整数 u,v,w,表示有一条 u 到 v 边权为 w 的无向边

保证数据是一棵树

输出描述:

一行一个整数,表示答案

示例1

输入

4
1 2 1
1 3 1
1 4 2

输出

5

说明

一种可能的方案为复制 <1,2,1> 这条边一次,欧拉路为4->1->2->1->3

就是将最长路之外的其他路走两遍,最长路只走一遍。

dfs求最长路,当前点的权值加上孩子中权值维护一个max值。

以任意点为根节点,遍历一遍树,得到结果。

代码实现:

/*
Look at the star
Look at the shine for U
*/
#include
#define ll long long
#define PII pair
#define sl(x) scanf("%lld",&x)
using namespace std;
const int N = 1e6+5;
const int mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1);
ll inv(ll b){if(b==1)return 1; return (mod-mod/b)*inv(mod%b)%mod;}
ll fpow(ll n,ll k){ll r=1;for(;k;k>>=1){if(k&1)r=r*n%mod;n=n*n%mod;}return r;}
ll dis[N];
struct node{
    ll next,w,v;
}p[N];
ll cnt = 0,head[N];
void add(ll u,ll v,ll w)
{
    p[cnt].w = w;
    p[cnt].v = v;
    p[cnt].next = head[u];
    head[u] = cnt++;
}
ll maxx;
void dfs(ll u,ll fa)
{
    for(int i = head[u];~i;i = p[i].next)
    {
        if(p[i].v != fa)
        {
            dfs(p[i].v,u);
            maxx = max(maxx,dis[u]+dis[p[i].v]+p[i].w);
            dis[u] = max(dis[u],dis[p[i].v]+p[i].w);
        }
    }
}

int main()
{
    ll n,i,j,k,u,v,w;
    sl(n);
    for(i = 0;i <= n;i++)
        head[i] = -1;
    ll ans = 0;
    n--;
    while(n--)
    {
        sl(u);sl(v);sl(w);
        add(u,v,w);
        add(v,u,w);
        ans += w;
    }
    dfs(1,-1);
    printf("%lld\n",ans*2-maxx);
    return 0;
}

 

你可能感兴趣的:(******搜索******,ACM的进阶之路)