bzoj1487: [HNOI2009]无归岛

依然环套树……不过那个状态转移方程好写多了……

无聊写了滚动数组结果……hehe(又是一节课的牺牲)……

 

type
  arr=record
    toward,next:longint;
  end;

const
  maxm=1000000;
  maxn=600000;

var
  edge:array[0..maxm]of arr;
  first,dfn,low,dep,num,value,fa:array[0..maxn]of longint;
  f:array[0..maxn,0..1]of longint;
  tot,n,m,time:longint;

function max(x,y:longint):longint;
begin
  if x<y then exit(y);
  exit(x);
end;

procedure addedge(j,k:longint);
begin
  inc(tot);
  edge[tot].toward:=k;
  edge[tot].next:=first[j];
  first[j]:=tot;
end;

procedure dp(x,root:longint);
var
  i,sum,j,l,k:longint;
  dp:array[0..1,0..1]of longint;
begin
  sum:=dep[x]-dep[root]+1;
  i:=x;
  while sum>0 do begin
    num[sum]:=i;
    i:=fa[i];
    dec(sum);
  end;
  sum:=dep[x]-dep[root]+1;
  dp[0,1]:=f[num[sum],1];
  dp[0,0]:=f[num[sum],0];
  l:=0;
  for i:=sum-1 downto 2 do begin
    j:=num[i];
    dp[1-l,0]:=max(dp[l,0],dp[l,1])+f[j,0];
    dp[1-l,1]:=dp[l,0]+f[j,1];
    l:=1-l;
  end;
  k:=max(dp[l,1],dp[l,0])+f[root,0]; //记住!!这里不能直接去更新f[root,0]因为下一步就要用到原始值233333
  l:=0;
  dp[0,1]:=f[root,1];
  dp[0,0]:=f[root,0];
  for i:=2 to sum do begin
    j:=num[i];
    dp[1-l,0]:=max(dp[l,0],dp[l,1])+f[j,0];
    dp[1-l,1]:=dp[l,0]+f[j,1];
    l:=1-l;
  end;
  f[root,0]:=k;
  f[root,1]:=dp[l,0];
end;

procedure tarjan(x:longint);
var
  i,too:longint;
begin
  inc(time);
  dfn[x]:=time;
  low[x]:=time;
  i:=first[x];
  f[x,1]:=value[x];
  while i>0 do begin
    too:=edge[i].toward;
    if too<>fa[x] then begin
      if dfn[too]=0 then begin
        fa[too]:=x;
        dep[too]:=dep[x]+1;
        tarjan(too);
        if low[x]>low[too] then low[x]:=low[too];
      end
      else
        if dfn[too]<low[x] then low[x]:=dfn[too];
      if dfn[x]<low[too] then begin
          f[x,1]:=f[x,1]+f[too,0];
          f[x,0]:=f[x,0]+max(f[too,0],f[too,1]);
        end;
    end;
    i:=edge[i].next;
  end;
  i:=first[x];
  while i>0 do begin
    too:=edge[i].toward;
    if (fa[too]<>x) and (dfn[x]<dfn[too]) then begin
      dp(too,x);
    end;
    i:=edge[i].next;
  end;
end;

procedure into;
var
  i,j,k:longint;
begin
  readln(n,m);
  for i:=1 to m do begin
    read(j,k);
    addedge(j,k);
    addedge(k,j);
  end;
  for i:=1 to n do read(value[i]);
end;

procedure work;
begin
  time:=0;
  dep[1]:=1;
  tarjan(1);
  writeln(max(f[1,0],f[1,1]));
end;

begin
  into;
  work;

end.
View Code

 

posted @ 2014-12-23 19:47  Macaulish  阅读(337)  评论(0编辑  收藏  举报