poj1848

来源:互联网 发布:天下三女号捏脸数据 编辑:程序博客网 时间:2024/06/02 03:30

【题意】

给定一颗n(n<=100)个点的树,求让每个在且只在一个环上最少需要添加的边数(一个环上起码要有三个点)

【输入】

第一行一个数n

接下来n行每行描述一条边

【输出】

如题意的答案


树形动态规划

每个点记录三个状态

0表示包括该点的子树全部在环上的最小代价

1表示该点在一条起码有两个点链上且除这条链上的点都在环上的最小代价

2表示该点在为链的起点且子数上的点全部在环上的最小代价

转移部分十分麻烦


program poj1848;const  inf=maxlongint div 100;var  tot,n,i,j,k,u,v:longint;  root:array [0..101] of longint;  next,point:array [0..201] of longint;  f:array [0..2,0..101] of longint;function min (a,b:longint):longint;begin  if a<b then exit(a)         else exit(b);end;procedure connect (u,v:longint);begin  inc(tot);  point[tot]:=v;  next[tot]:=root[u];  root[u]:=tot;end;procedure dfs (now,father:longint);var  i,sum,first,second,q,p:longint;begin  i:=root[now];  first:=0;  second:=0;  sum:=0;  q:=0;  p:=0;  while i<>0 do    begin      if point[i]<>father then        begin          dfs(point[i],now);          sum:=sum+f[0,point[i]];          if -f[0,point[i]]+f[1,point[i]]<-f[0,first]+f[1,first] then            begin              second:=first;              first:=point[i];            end                                                                 else          if -f[0,point[i]]+f[1,point[i]]<-f[0,second]+f[1,second] then            second:=point[i];          if -f[0,point[i]]+min(f[1,point[i]],f[2,point[i]])<          -f[0,q]+min(f[1,q],f[2,q]) then            begin              p:=q;              q:=point[i];            end                                     else          if -f[0,point[i]]+min(f[1,point[i]],f[2,point[i]])<          -f[0,p]+min(f[1,p],f[2,p]) then            p:=point[i];        end;      i:=next[i];    end;  f[2,now]:=sum;  if first=0 then    begin      f[0,now]:=inf;      f[1,now]:=inf;      exit;    end;  if second=0 then    begin      f[0,now]:=f[1,first]+1;      f[1,now]:=min(f[1,first],f[2,first]);      exit;    end;  f[0,now]:=min(sum-f[0,first]+f[1,first]+1,  sum-f[0,q]+min(f[1,q],f[2,q])-f[0,p]+min(f[1,p],f[2,p])+1);  f[1,now]:=sum-f[0,q]+min(f[1,q],f[2,q]);end;begin  read(n);  tot:=0;  for i:=1 to n - 1 do    begin      read(u,v);      connect(u,v);      connect(v,u);    end;  f[1,0]:=maxlongint div 10;  f[2,0]:=maxlongint div 10;  dfs(1,0);  if f[0,1]>=inf then writeln(-1)                 else writeln(f[0,1]);end.