牛客练习赛40 C 小A与欧拉路(树的直径)

链接:https://ac.nowcoder.com/acm/contest/369/C

题目描述

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

输入描述:

第一行一个数 n ,表示节点个数
接下来 n-1 行,每行三个整数 u,v,w,表示有一条 u 到 v 边权为 w 的无向边
保证数据是一棵树

输出描述:

一行一个整数,表示答案

输入

4
1 2 1
1 3 1
1 4 2

输出

5

题意:找一条最短路,可以遍历所有树的节点
题意:这是博主第二次写这种题了,只要找到树的直径,然后用 总权值*2-直径的权值 就是答案
本来以为可以直接a掉 结果脑残的用了刚刚学会的链式前向星,没有注意双向边数组两倍的细节 超时到自闭
#include <cstdio>
#include <map>
#include <iostream>
#include<cstring>
#include<bits/stdc++.h>
#define ll long long int
#define M 6
using namespace std;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
int moth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int dir[4][2]={1,0 ,0,1 ,-1,0 ,0,-1};
int dirs[8][2]={1,0 ,0,1 ,-1,0 ,0,-1, -1,-1 ,-1,1 ,1,-1 ,1,1};
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
int n,cnt;
struct node{
    int next;
    int to;
    int w;
};
node edge[400007];
int head[400007];
bool vis[400007];
void add(int u,int v,int w){
    edge[++cnt].next=head[u];
    edge[cnt].to=v;
    edge[cnt].w=w;
    head[u]=cnt;
}
ll ans;
int ss;
void dfs(int pos,ll v){
    vis[pos]=1;
    for(int i=head[pos];i!=0;i=edge[i].next){
        if(vis[edge[i].to]) continue;
        dfs(edge[i].to,v+edge[i].w);
            vis[edge[i].to]=0;
    }
    if(v>ans){
        ans=v;
        ss=pos;
    }
}
int main(){
    while(~scanf("%d",&n)){
        ll sum=0;
        memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
        cnt=0;
        for(int i=1;i<n;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            sum+=w;
            add(u,v,w);
            add(v,u,w);
        }
        ans=0;
        dfs(1,0);
        vis[1]=0;
        ans=0;
        dfs(ss,0);
        printf("%lld\n",sum*2-ans);
    }
}

猜你喜欢

转载自www.cnblogs.com/wmj6/p/10386387.html