bzoj 1912 巡逻(树直径)

Description

Input

第一行包含两个整数 n, K(1 ≤ K ≤ 2)。接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n)。

Output

输出一个整数,表示新建了K 条道路后能达到的最小巡逻距离。

Sample Input

8 1
1 2
3 1
3 4
5 3
7 5
8 5
5 6

Sample Output

11

HINT

10%的数据中,n ≤ 1000, K = 1; 
30%的数据中,K = 1; 
80%的数据中,每个村庄相邻的村庄数不超过 25; 
90%的数据中,每个村庄相邻的村庄数不超过 150; 
100%的数据中,3 ≤ n ≤ 100,000, 1 ≤ K ≤ 2。

首先对于k=1的数据,yy一下就可以发现要找树的直径,然而对于k=2的点,相当于找两条直径,但是会发现,如果这两条直径重复了会很蛋疼,还是会重复走到,因此我们找完第一个直径后,直径上面的边全部赋值为-1,然后再找第二条直径。
 
 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 int tot,go[200005],first[100005],next[200005];
 7 int op[200005];
 8 int vis[100005],dis[100005],c[200005],from[100005],pre[100005];
 9 int d[100005],n,k,ans,Mx2,val[200005];
10 void insert(int x,int y,int z){
11     tot++;
12     go[tot]=y;
13     next[tot]=first[x];
14     first[x]=tot;
15     val[tot]=z;
16 }
17 void add(int x,int y,int z){
18     insert(x,y,z);op[tot]=tot+1;
19     insert(y,x,z);op[tot]=tot-1;
20 }
21 void bfs(int x){
22     int h=0,t=1;
23     for (int i=1;i<=n;i++) pre[i]=from[i]=0;
24     for (int i=1;i<=n;i++) vis[i]=0,dis[i]=0;
25     c[1]=x;vis[x]=1;dis[x]=0;
26     while (h<=t){
27         h++;
28         for (int i=first[c[h]];i;i=next[i]){
29             int pur=go[i];
30             if (vis[pur]) continue;
31             pre[pur]=c[h];
32             from[pur]=i;
33             vis[pur]=1;c[++t]=pur;dis[pur]=dis[c[h]]+val[i];
34         }
35     }
36 }
37 void pianfen1(){
38     bfs(1);
39     int mx=1;
40     for (int i=2;i<=n;i++) if (dis[i]>dis[mx]) mx=i;
41     bfs(mx);
42     Mx2=1;
43     for (int i=2;i<=n;i++) if (dis[Mx2]<dis[i]) Mx2=i;
44     if (k==1) printf("%d
",2*(n-1)-dis[Mx2]+1);
45 }
46 void dfs(int x){
47     d[x]=0,vis[x]=1;int mx1=0,mx2=0;
48     for (int i=first[x];i;i=next[i]){
49         int pur=go[i];
50         if (vis[pur]) continue;
51         dfs(pur);
52         if (d[pur]+val[i]>mx1) mx2=mx1,mx1=d[pur]+val[i];
53         else
54         if (d[pur]+val[i]>mx2) mx2=d[pur]+val[i];
55     }
56     if (mx1+mx2>ans) ans=mx1+mx2;
57     d[x]=mx1;
58 }
59 int main(){
60     scanf("%d%d",&n,&k);
61     for (int i=1;i<n;i++){
62         int x,y;
63         scanf("%d%d",&x,&y);
64         add(x,y,1);
65     }
66     pianfen1();
67     int cnt=2*(n-1)-dis[Mx2]+1;
68     if (k==1) return 0;
69     for (int i=1;i<=n;i++) vis[i]=0,d[i]=0x3f3f3f3f;
70     for (int i=Mx2;i!=0;i=pre[i]) val[from[i]]=-1,val[op[from[i]]]=-1;
71     ans=0;
72     dfs(1);
73     
74     printf("%d
",cnt-ans+1);
75 }
原文地址:https://www.cnblogs.com/qzqzgfy/p/5535821.html