小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
备注:
1≤n≤2×1051≤n≤2×105
1≤ui,vi≤n1≤ui,vi≤n
1≤wi≤1041≤wi≤104
解题报告:
思维题,不难发现选择树的直径,剩下的挂到链上,这样一定是最优解。
AC代码:
using namespace std;
const int MAX = 6e5 + 5 ;
const int INF = 0x3f3f3f3f;
struct Node {
int to;
int w;
int ne;
} e[MAX];
struct point {
int pos,c;
point(){}
point(int pos,int c):pos(pos),c(c){}
};
int n;
int head[MAX];
int cnt = 0 ;
bool vis[MAX];
void init() {
cnt = 0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w) {
e[cnt].to = v;
e[cnt].w = w;
e[cnt].ne = head[u];
head[u] = cnt;
cnt++;
}
int bfs(int x,int &w) {
queue <point> q;
int maxx = 0;
int retp = x ;//返回的点坐标
memset(vis,0,sizeof(vis) );
q.push(point(x,0));vis[x] = 1;
point now;
while(q.size() ) {
point cur = q.front();
q.pop();
for(int i = head[cur.pos]; i!=-1; i=e[i].ne) {
if(vis[e[i].to]) continue;
vis[e[i].to] = 1;
now.pos = e[i].to;
now.c = cur.c + e[i].w;
if(now.c>maxx) {
maxx = now.c;
retp = now.pos;
}
q.push(now);
}
//w = maxx;
}
w = maxx;
return retp;
}
int main()
{
cin>>n;
init();
int u,v,w;
ll sum = 0;
for(int i = 1; i<=n-1; i++) {
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
sum += w;
}
int ans1 = 0,ans2 = 0;
u = bfs(1,ans1);
v = bfs(u,ans2);
//printf("ans2 = %d\n",ans2);
printf("%lld\n",1LL*ans2 + (sum-ans2)*2);
return 0 ;
}
/*
9
1 8 1
1 2 2
2 7 3
2 3 1
3 5 3
3 4 10
4 9 4
5 6 2
*/