Highway
In ICPCCamp there were n towns conveniently numbered with 1,2,…,n connected with (n−1) roads. The i-th road connecting towns ai and bi has length ci. It is guaranteed that any two cities reach each other using only roads.
Bobo would like to build (n−1) highways so that any two towns reach each using only highways. Building a highway between towns x and y costs him δ(x,y) cents, where δ(x,y) is the length of the shortest path between towns x and y using roads.
As Bobo is rich, he would like to find the most expensive way to build the (n−1) highways.
Input
The input contains zero or more test cases and is terminated by end-of-file. For each test case:
The first line contains an integer n. The i-th of the following (n−1) lines contains three integers ai, bi and ci.
1≤n≤105
1≤ai,bi≤n
1≤ci≤108
The number of test cases does not exceed 10.
Output
For each test case, output an integer which denotes the result.
Sample Input
5
1 2 2
1 3 1
2 4 2
3 5 1
5
1 2 2
1 4 1
3 4 1
4 5 2
Sample Output
19
15
题目链接: http://202.197.224.59/OnlineJudge2/index.php/Problem/index/p/13/
或 https://www.icpc-camp.org/contests/4mYguiUR8k0GKE
题目大意:
给出一棵无根树,给出n-1条边和权值,然后让你求重新选择n-1条边使其联通并且权和最大
官方题解:
首先有一点得知道,关于树的直径
树的直径是指树上权值和最大的路径(最简单路径,即每一个点只经过一次)
存在结论:对于树上的任意一个节点,距离这个节点最远的距离一定是到直径的端点的距离
就是先求出树的最远点对(树的直径的端点)d1,d2,再求出以直径的两个端点为起点的disi,首先将直径(d1,d2的距离)加入集合,对于其他点i,加入max(d1到i的距离,d2到i的距离)到集合,集合所构成的树就是题目的答案
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 100100;
struct node
{
int u,v,w;
int next;
} e[maxn<<1];
long long dis[maxn],dd[maxn];
int head[maxn];
int top;
bool vis[maxn];
void init()
{
memset(dis,0,sizeof(dis));
memset(head,-1,sizeof(head));
memset(vis,false,sizeof(vis));
top = 0;
}
void add(int u,int v,int w)
{
e[top].u = u;
e[top].v = v;
e[top].w = w;
e[top].next = head[u];
head[u] = top++;
}
int bfs(int s)//求树的直径
{
queue<int>q;
vis[s] = true;
q.push(s);
int key = - 1;
long long mmax = 0;
while(!q.empty())
{
int t = q.front();
q.pop();
for(int i=head[t]; ~i; i=e[i].next)
{
int v = e[i].v;//当前思想,把这个点看成结果理解下面的if
if(!vis[v]&&dis[v]//最大路判断
{
vis[v] = true;
dis[v] = dis[t]+e[i].w;
q.push(v);
if(dis[v]>mmax)
{
mmax = dis[v];
key = v;
}
}
}
}
return key;
}
void bfs1(int s)
{
queue<int>q;
vis[s] = true;
q.push(s);
while(!q.empty())
{
int t = q.front();
q.pop();
for(int i=head[t]; ~i; i =e[i].next)
{
int v = e[i].v;
if(!vis[v]&&dis[v]true;
dis[v] = dis[t]+e[i].w;
dd[v] = max(dis[v],dd[v]);
q.push(v);
}
}
}
}
int main()
{
int n,u,v,w;
while(cin>>n)
{
init();
memset(dd,0,sizeof(dd));
for(int i=0; i1; i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
int a = bfs(1);
memset(vis,false,sizeof(vis));
memset(dis,0,sizeof(dis));
int b = bfs(a);
long long sum = dis[b];
memset(vis,false,sizeof(vis));
memset(dis,0,sizeof(dis));
bfs1(a);
memset(vis,false,sizeof(vis));
memset(dis,0,sizeof(dis));
bfs1(b);
for(int i=1; i<=n; i++)
{
if(i==a||i==b)
continue;
sum+=dd[i];
}
cout<return 0;
}
参考:
http://blog.csdn.net/bless924295/article/details/72331272
http://blog.csdn.net/liangzhaoyang1/article/details/72796738