您的位置:首页 > 理论基础 > 计算机网络

Bzoj 1596: [Usaco2008 Jan]电话网络

2016-10-30 22:31 295 查看
原题网址:http://www.lydsy.com/JudgeOnline/problem.php?id=1596

有点像“没有上司的舞会”,但因为两座塔可以距离最多为3,所以要记三种状态。f[x]表示x这个点已经放了,g[x]表示x这个点没放但已经子树的通讯塔范围内了,h[x]表示x这个点没放而且不在子树的通讯塔范围内。f[x]直接由每个子树三种状态取最小转移即可,g[x]由每个子树f[y]和g[y]取小的转移即可,但要注意至少要取一个f[y],h[x]直接由子树g[y]转移得。

type
edge=record
y,next:longint;
end;
const
INF=10001;
var
map:array[0..20050] of edge;
f,g,h,first:array[0..10050] of longint;
n,i,x,y,s:longint;
function min(a,b:longint):longint;
begin if (a<b) then exit(a) else exit(b); end;
procedure ins(x,y:longint);
begin
inc(s);map[s].y:=y;
map[s].next:=first[x];first[x]:=s;
end;
procedure dfs(x,fa:longint);
var
t,det,y:longint;
put:boolean;
begin
f[x]:=1;g[x]:=0;h[x]:=0;
t:=first[x];
det:=INF;put:=false;
while (t>0) do
begin
y:=map[t].y;
if (y<>fa) then
begin
dfs(y,x);
inc(f[x],min(min(f[y],g[y]),h[y]));
if (f[y]<=g[y])
then
begin
put:=true;
inc(g[x],f[y]);
end
else
begin
inc(g[x],g[y]);
det:=min(det,f[y]-g[y]);
end;
inc(h[x],g[y]);
end;
t:=map[t].next;
end;
if (not put)
then g[x]:=g[x]+det;
end;
begin
read(n);
for i:=1 to n-1 do
begin
read(x,y);
ins(x,y);
ins(y,x);
end;
dfs(1,0);
writeln(min(f[1],g[1]));
end.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Bzoj 树形dp