POJ1849 Two——贪心——Pku1849

类似于树形动态规划的贪心。题目大意:

这个城市由节点和连接节点的街道组成,街道是双向的。此刻大雪覆盖了这个城市,市长确定了一些街道要将它们清扫干净,这些街道的确定保证所有节点可以通过它们连通而且街道数目尽可能小。有两台相同的扫雪机SM,它们的起点在同一个节点上。

所有被确定的街道必须至少被一台扫雪机经过,才能完成清扫任务,完成任务后SM可以在原地停下,不必集合到某一点。扫雪机的行进是需要耗费油量的(即使扫雪机行驶的是已被扫净的街道),因此扫雪机行进的总距离越小越好,你需要计算两台扫雪机完成任务的最小总行进距离。

 

{以上感谢铎铎大牛提供的翻译}

 

解法:

首先从根节点出发找到一条最长的链,然后将这条链上路径的长度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.



你可能感兴趣的:(poj)