1040: [ZJOI2008]骑士 - BZOJ

Description

Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英。他们劫富济贫,惩恶扬善,受到社会各界的赞扬。最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争。战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队。于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶。骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾。每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出征的。战火绵延,人民生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给了你一个艰巨的任务,从所有的骑士中选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的情况),并且,使得这支骑士军团最具有战斗力。为了描述战斗力,我们将骑士按照1至N编号,给每名骑士一个战斗力的估计,一个军团的战斗力为所有骑士的战斗力总和。
Input

第一行包含一个正整数N,描述骑士团的人数。接下来N行,每行两个正整数,按顺序描述每一名骑士的战斗力和他最痛恨的骑士。
Output

应包含一行,包含一个整数,表示你所选出的骑士军团的战斗力。
Sample Input
3
10 2
20 3
30 1
Sample Output
30
【数据规模】
对于30%的测试数据,满足N ≤ 10;
对于60%的测试数据,满足N ≤ 100;
对于80%的测试数据,满足N ≤ 10 000。
对于100%的测试数据,满足N ≤ 1 000 000,每名骑士的战斗力都是不大于 1 000 000的正整数。

 

一个图分为几个联通块,每个块有且只有一个环,求最大点权独立集(是这样说的吗,我瞎编的.......)

先用tarjan求出一个环上的两点,然后分为两种情况树dp

一是A不选,二是B不选,两者选最优(不选但是不要直接把点删掉,因为删掉可能会把这个联通块分成几部分,所以dp时只要把它被选的情况的最优值减去它的权值就行了)

  1 const
  2     maxn=1000010;
  3 var
  4     first,next,last,cut:array[0..maxn*2]of longint;
  5     f:array[0..maxn,0..1]of int64;
  6     node,flag,a,dfn:array[0..maxn]of longint;
  7     n,tot,num,time,d:longint;
  8     ans:int64;
  9  
 10 procedure insert(x,y:longint);
 11 begin
 12     inc(tot);
 13     last[tot]:=y;
 14     next[tot]:=first[x];
 15     first[x]:=tot;
 16 end;
 17  
 18 procedure dfs(x:longint);
 19 var
 20     i:longint;
 21 begin
 22     flag[x]:=time;
 23     inc(d);
 24     dfn[x]:=d;
 25     i:=first[x];
 26     while i<>0 do
 27       begin
 28         if cut[i]<>time then
 29         begin
 30           if flag[last[i]]<>time then
 31             begin
 32               cut[i xor 1]:=time;
 33               dfs(last[i]);
 34             end
 35           else
 36             if dfn[last[i]]<dfn[x] then
 37             begin
 38               inc(num);
 39               node[num]:=x;
 40               inc(num);
 41               node[num]:=last[i];
 42             end;
 43         end;
 44         i:=next[i];
 45       end;
 46 end;
 47  
 48 procedure init;
 49 var
 50     i,x:longint;
 51 begin
 52     read(n);
 53     tot:=1;
 54     for i:=1 to n do
 55       begin
 56         read(a[i],x);
 57         insert(i,x);
 58         insert(x,i);
 59       end;
 60     inc(time);
 61     for i:=1 to n do
 62       if flag[i]<>time then dfs(i);
 63 end;
 64  
 65 function max(x,y:int64):int64;
 66 begin
 67     if x>y then exit(x);
 68     exit(y);
 69 end;
 70  
 71 procedure dp(x:longint);
 72 var
 73     i:longint;
 74 begin
 75     flag[x]:=time;
 76     f[x,1]:=a[x];
 77     f[x,0]:=0;
 78     i:=first[x];
 79     while i<>0 do
 80       begin
 81         if flag[last[i]]<>time then
 82         begin
 83           dp(last[i]);
 84           inc(f[x,1],f[last[i],0]);
 85           inc(f[x,0],max(f[last[i],1],f[last[i],0]));
 86         end;
 87         i:=next[i];
 88       end;
 89 end;
 90  
 91 procedure work;
 92 var
 93     i:longint;
 94     sum:int64;
 95 begin
 96     for i:=1 to num>>1 do
 97       begin
 98         inc(time);
 99         dp(node[i<<1]);
100         sum:=max(f[node[i<<1],1]-a[node[i<<1]],f[node[i<<1],0]);
101         inc(time);
102         dp(node[i<<1-1]);
103         sum:=max(sum,max(f[node[i<<1-1],1]-a[node[i<<1-1]],f[node[i<<1-1],0]));
104         inc(ans,sum);
105       end;
106     write(ans);
107 end;
108  
109 begin
110     init;
111     work;
112 end.
View Code

 

posted @ 2014-04-01 08:30  Randolph87  阅读(265)  评论(0)    收藏  举报