P1912: [Apio2010]patrol 巡逻
这道题讨论了好久,一直想不明白,如果按传统的随便某一个点出发找最长链,再回头,K=2 的时候赋了-1就没法用这种方法找最长链了,于是乎,更强的找最长链的方法就来了。。类似于DP的东西吧。先上代码:
1 const maxn=100002;
2 type
3 node=record
4 f,t,l:longint;
5 end;
6 var n,k,i,j,ans,num,f,t,diameter,s,sum:longint;
7 b:array[0..2*maxn] of node;
8 head,go1,go2:array[0..maxn] of longint;
9 procedure swap(var a,b:longint);
10 var tem:longint;
11 begin
12 tem:=a; a:=b; b:=tem;
13 end;
14 procedure insert(num,f,t:longint);
15 begin
16 b[num].f:=head[f];
17 b[num].t:=t;
18 b[num].l:=1;
19 head[f]:=num;
20 end;
21 function dfs(x,f:longint):longint;
22 var nowe,max1,max2,tem:longint;
23 begin
24 max1:=0; max2:=0; //tem:=0;
25 nowe:=head[x];
26 while nowe<>0 do
27 begin
28 if b[nowe].t=f then
29 begin
30 nowe:=b[nowe].f;
31 continue;
32 end;
33 tem:=dfs(b[nowe].t,x)+b[nowe].l;
34 if tem>max1 then begin
35 go2[x]:=go1[x];
36 go1[x]:=nowe;
37 max2:=max1;
38 max1:=tem;
39 end
40 else if tem>max2 then
41 begin
42 go2[x]:=nowe;
43 max2:=tem;
44 end;
45 nowe:=b[nowe].f;
46 end;
47 if diameter<max1+max2 then
48 begin
49 diameter:=max1+max2;
50 s:=x;
51 end;
52 exit(max1);
53 end;
54 begin
55 readln(n,k);
56 for i:=1 to n-1 do
57 begin
58 readln(f,t);
59 insert(i*2-1,f,t);
60 insert(i*2,t,f);
61 end;
62 ans:=2*(n-1);
63 diameter:=0;
64 sum:=dfs(1,0);
65 ans:=ans-diameter+1;
66 if k>1 then
67 begin
68 diameter:=0;
69 i:=go1[s];
70 while i<>0 do
71 begin
72 b[i].l:=-1;
73 i:=go1[b[i].t];
74 end;
75 i:=go2[s];
76 while i<>0 do
77 begin
78 b[i].l:=-1;
79 i:=go1[b[i].t];
80 end;
81 t:=dfs(1,0);
82 ans:=ans-diameter+1;
83 end;
84 writeln(ans);
85 end.
1 int diameter,s; //树的直径为diameter,直径的起点是s
2 int son1[MAXV],son2[MAXV]; //记录最长路与次长路的路径
3
4 int DFS(int u,int fa)
5 {
6 int max1=0,max2=0; //与当前点相连的最长路与次长路 之和为不过fa的最长链,或者与fa相连并 //加上与fa相连边权值,作为连接fa可能的max1 或 max2
7 for(int p=head[u];p!=-1;p=edges[p].next)
8 {
9 int v=edges[p].v;
10 if(v==fa) continue; //一直往下走,直到叶子节点
11 int nowh=DFS(v,u)+edges[p].w;
12 if(nowh>max1) max2=max1,son2[u]=son1[u],max1=nowh,son1[u]=p;
13 else if(nowh>max2) max2=nowh,son2[u]=p;
14 }
15 if(diameter<max1+max2) diameter=max1+max2,s=u;
16 return max1;
17 }
而复杂度也是 O(n)的。
(转载请注明出处:http://www.cnblogs.com/Kalenda/)