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

 

你可能感兴趣的:(2008)