1. 程式人生 > >牛客練習賽40 C 小A與歐拉路(樹的直徑)

牛客練習賽40 C 小A與歐拉路(樹的直徑)

scan pac 並且 找到 get \n com 沒有 tle

鏈接: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); } }

牛客練習賽40 C 小A與歐拉路(樹的直徑)