题意:一个城镇的道路是树形的,每条道路有对应的长度。因为下雪,每条道路都被雪覆盖了。现在有两个人从给定的点S出发,分别驾驶扫雪车去扫雪。问题是:在将所有的道路上积雪全部清理的情况下 ,最小化两人走过的路程。两个人没有必要回到起始点S。
思路:通过手算可以发现,扫雪的过程中,有一些路会走两遍,有一些路会走一遍。两遍是因为我们要回到原来的节点,向另外一个子节点继续进行扫雪。
所以,为了能够最小化走过的路程,我们要将长度长的路只走一遍。
因为两个人的起始点相同,他们只走一遍的路就连成了树上两点的路径。
树上两点最远的距离就是树的直径了。
所以,最终的答案是
2(∑ e∈E e.w)−diameter
树的直径可以两遍DFS得到。
代码如下:
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAX = 100010;
struct edge{
int t,w;
edge(){}
edge(int tt,int ww):t(tt),w(ww){}
} edges[MAX<<1];
int N,K;
int nxt[MAX<<1],head[MAX],tot;
int d[MAX];
void init()
{
memset(head,-1,sizeof(head));
tot = 0;
}
void addedge(int u, int v,int w)
{
edges[tot] = edge(v,w), nxt[tot] = head[u];
head[u] = tot++;
edges[tot] = edge(u,w), nxt[tot] = head[v];
head[v] = tot++;
}
void dfs(int u, int p, int dis)
{
d[u] = dis;
for(int i = head[u]; ~i; i = nxt[i]){
edge & e = edges[i];
if(e.t == p) continue;
dfs(e.t,u,dis+e.w);
}
}
int main(void)
{
//freopen("input.txt","r",stdin);
int N,S,sum = 0;
scanf("%d%d",&N,&S);
init();
for(int i = 0; i < N -1; ++i){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
sum += 2 * c;
}
dfs(1,0,0);
int u = 0, dis = 0;
for(int i = 1; i <= N; ++i){
if(dis < d[i]){
dis = d[i];
u = i;
}
}
dfs(u,0,0);
dis = 0;
for(int i = 1; i <= N; ++i)
dis = max(dis,d[i]);
printf("%d\n",sum - dis);
return 0;
}