论环形dp的重要!

其实这个环比较简单,稍微分析一下就知道,

这是一个简单环,并且每个联通块里只含有一个。

我觉得把处理环的关键,就是要找出环形和线形(树形)有什么区别。

如果我们从某处断开的做dp的话,转移的结果只对根节点有影响(不确定);

然后我猜测应该只要找到环上相邻两点然后断开分别以他们为根做treedp就可以了

结果真的是这样……

总感觉缺点什么……

有待进一步思考……

 1 type node=record
 2        point,next:longint;
 3      end;
 4 
 5 var edge:array[0..2000010] of node;
 6     can:array[0..2000010] of boolean;
 7     v:array[0..1000010] of boolean;
 8     p,w:array[0..1000010] of longint;
 9     f:array[0..1000010,0..1] of int64;
10     len,find,n,u,z,i:longint;
11     ans,res:int64;
12 
13 function max(a,b:int64):int64;
14   begin
15     if a>b then exit(a) else exit(b);
16   end;
17 
18 procedure add(x,y:longint);
19   begin
20     inc(len);
21     edge[len].point:=y;
22     edge[len].next:=p[x];
23     can[len]:=true;
24     p[x]:=len;
25   end;
26 
27 procedure dfs(x:longint);   //找环
28   var i,y:longint;
29   begin
30     v[x]:=true;
31     i:=p[x];
32     while i<>-1 do
33     begin
34       y:=edge[i].point;
35       if can[i] and not v[y] then   
36       begin
37         can[i xor 1]:=false;   //注意防止因为同一条边而回头
38         dfs(y);
39         can[i xor 1]:=true;    //解除标记
40       end
41       else if can[i] and v[y] then
42       begin
43         u:=x;
44         z:=y;
45         find:=i;
46       end;
47       i:=edge[i].next;
48     end;
49   end;
50 
51 procedure treedp(x:longint);
52   var i,y:longint;
53   begin
54     i:=p[x];
55     f[x,0]:=0;
56     f[x,1]:=w[x];
57     while i<>-1 do
58     begin
59       y:=edge[i].point;
60       if can[i] then   
61       begin
62         can[i xor 1]:=false;
63         treedp(y);
64         can[i xor 1]:=true;
65         f[x,0]:=f[x,0]+max(f[y,0],f[y,1]);  //基本的treedp
66         f[x,1]:=f[x,1]+f[y,0];
67       end;
68       i:=edge[i].next;
69     end;
70   end;
71 
72 procedure dp(i:longint);
73   begin
74     dfs(i);
75     can[find]:=false;    //断开
76     can[find xor 1]:=false;
77     treedp(u);
78     res:=f[u,0];
79     treedp(z);
80     ans:=ans+max(f[z,0],res);  //都是不取根,这里是凭感觉写的,欢迎指教
81   end;
82 
83 begin
84   len:=-1;
85   readln(n);
86   fillchar(p,sizeof(p),255);
87   for i:=1 to n do
88   begin
89     readln(w[i],z);
90     add(z,i);
91     add(i,z);
92   end;
93   for i:=1 to n do
94     if not v[i] then dp(i);
95   writeln(ans);
96 end.
View Code

 

posted on 2014-06-29 23:05  acphile  阅读(214)  评论(0编辑  收藏  举报