类似于树形动态规划的贪心。题目大意:
这个城市由节点和连接节点的街道组成,街道是双向的。此刻大雪覆盖了这个城市,市长确定了一些街道要将它们清扫干净,这些街道的确定保证所有节点可以通过它们连通而且街道数目尽可能小。有两台相同的扫雪机S和M,它们的起点在同一个节点上。
所有被确定的街道必须至少被一台扫雪机经过,才能完成清扫任务,完成任务后S和M可以在原地停下,不必集合到某一点。扫雪机的行进是需要耗费油量的(即使扫雪机行驶的是已被扫净的街道),因此扫雪机行进的总距离越小越好,你需要计算两台扫雪机完成任务的最小总行进距离。
{以上感谢铎铎大牛提供的翻译}
解法:
首先从根节点出发找到一条最长的链,然后将这条链上路径的长度len全部设为-len
再从根节点出发找到一条最长的连
树中每条边的长度之和*2-两条链的长度之和就是答案。
贪心证明:显然,画画图就明白了
CODE
Program Two;//By_thispoet Const maxn=300000; Var p,q,i,j,k,m,n,s,tmp,ans :Longint; pre,other,last,len :Array[0..maxn]of Longint; size,father,deal,res,kset :Array[0..maxn]of Longint; flag,v :Array[0..maxn]of Boolean; Procedure Dfs(i:Longint); var j,k:Longint; begin j:=last[i]; while j<>0 do begin k:=other[j]; if k<>father[i] then begin father[k]:=i; if flag[k] then size[k]:=size[i]+len[j] else size[k]:=size[i]-len[j]; Dfs(k); end; j:=pre[j]; end; end; BEGIN readln(n,s); for i:=1 to n-1 do begin readln(p,q,m); inc(k);pre[k]:=last[p];last[p]:=k;other[k]:=q;len[k]:=m; inc(k);pre[k]:=last[q];last[q]:=k;other[k]:=p;len[k]:=m; inc(ans,m*2); end; fillchar(flag,sizeof(flag),1); size[s]:=0; Dfs(s); tmp:=1; for i:=2 to n do if size[i]>size[tmp] then tmp:=i; p:=size[tmp]; while tmp<>s do begin j:=last[tmp]; while other[j]<>father[tmp] do j:=pre[j]; flag[tmp]:=false; tmp:=father[tmp]; end; Dfs(s); tmp:=1; for i:=2 to n do if size[i]>size[tmp] then tmp:=i; inc(p,size[tmp]); dec(ans,p); writeln(ans); END.