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.
View Code

 

 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 }
View Code

而复杂度也是 O(n)的。

(转载请注明出处:http://www.cnblogs.com/Kalenda/)

posted @ 2015-09-22 16:42  LovelyMonster丶  阅读(204)  评论(0编辑  收藏  举报