码迷,mamicode.com
首页 > 其他好文 > 详细

1040: [ZJOI2008]骑士

时间:2014-12-19 21:59:31      阅读:298      评论:0      收藏:0      [点我收藏+]

标签:

    首先是因为想学仙人掌图才来先拿这题热热身,结果&……竟然调了一个晚上我的傻叉!(其中一大半的时候是在郁闷hzwer和Greens的代码画风不一样,后来才发现一个用拓扑一个用树dp23333,以后代码坚决自己解决

 

贴一下hzwer大神的题解吧:http://hzwer.com/1729.html

以及云的代码:http://hi.baidu.com/greencloud/archive/tag/dp?page=4

 

treedp:
首先我们发现一个骑士只会觉得另一个骑士丑(233),然后我们想到了树,因为树上每个点只有一个入度,所以边建为从被讨厌的人指向讨厌他的。但是会出现环的情况……这时候一定是在树根那里有个环!(画图就可以发现一定是这样,如果不是在树根那么就会有出现入度为2的情况,显然不可能……)。然后就先处理出不再环上的每个点与各自的子树的情况(dp[x,0]表示x取,dp[x,1],表示x不取),由于树上只有一个环,so那些环上的点的儿子们如果不再环上那子树一定是棵树不会出现环,so是可以用treedp递归处理出来。(然后拓扑的方法就相反啦,边是从某个人指向这个人讨厌的人,那么那些入度为0的点就是老好人,然后从这些老好人开始推,找老好人讨厌的人&……算过去)

 

然后就是处理环上怎么取最大的问题啦。

破环成链,这时候就先不考虑链头与链尾不能同时取的情况,跑一边dp,然后再来考虑链头和链尾的限制,也就是链头取的时候链尾不能取,链头不取的时候链尾可取可不取……

(我X我最近什么鬼状态!!!连傻叉题都不会写了)

技术分享
type
  arr=record
    toward,next:longint;
  end;

const
  maxn=1002333;

var
  edge:array[0..maxn]of arr;
  first,fa,link,from:array[0..maxn]of longint;
  value:array[0..maxn]of int64;
  chose:array[0..maxn]of boolean;
  dp:array[0..maxn,0..1]of int64;
  f:array[0..maxn,1..4]of int64;
  n,m,tot:longint;

function max(x,y:int64):int64;
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 treedp(x:longint);
var
  i,too:longint;
begin
  dp[x,1]:=value[x];
  dp[x,0]:=0;
  chose[x]:=false;
  i:=first[x];
  while i>0 do begin
    too:=edge[i].toward;
    treedp(too);
    dp[x,0]:=dp[x,0]+max(dp[too,0],dp[too,1]);
    dp[x,1]:=dp[x,1]+dp[too,0];
    i:=edge[i].next;
  end;
end;

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

procedure work;
var
  i,j,x,now,sum,too:longint;
  ans,answer:int64;
begin
  answer:=0;
  for i:=1 to n do
    if chose[i] then begin
      sum:=0;
      x:=i;
      while chose[x] do begin
        chose[x]:=false;
        x:=fa[x];
        //from[fa[x]]:=x;
        from[fa[x]]:=x;
      end;
      now:=x;
      repeat
        j:=first[x];
        dp[x,1]:=value[x];
        while j>0 do  begin
          too:=edge[j].toward;
          if too<>from[x] then begin
            treedp(too);
            dp[x,0]:=dp[x,0]+max(dp[too,0],dp[too,1]);
            dp[x,1]:=dp[x,1]+dp[too,0];
          end;
          j:=edge[j].next;
        end;
        inc(sum);
        link[sum]:=x;
        x:=fa[x];
      until x=now;
      ans:=0;
      f[1,1]:=dp[link[1],0];
      f[1,2]:=dp[link[1],1];
      f[1,3]:=dp[link[1],0];
      f[1,4]:=dp[link[1],0];
      for j:=2 to sum do begin
        x:=link[j];
        f[j,1]:=max(f[j-1,1],f[j-1,2])+dp[x,0];
        f[j,2]:=f[j-1,1]+dp[x,1];
        f[j,3]:=max(f[j-1,3],f[j-1,4])+dp[x,0];
        f[j,4]:=f[j-1,3]+dp[x,1];
      end;
      ans:=max(f[sum,1],f[sum,3]);
      ans:=max(ans,f[sum,4]);
      answer:=answer+ans;
    end;
  writeln(answer);
end;

begin
  into;
  work;
end.
View Code

 

1040: [ZJOI2008]骑士

标签:

原文地址:http://www.cnblogs.com/Macaulish/p/4174741.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!