BZOJ 1912 patrol patrol

Description

Input

The first line contains two integers n, K (1 ≤ K ≤ 2). Next, n - 1 lines of two integers a, b, it indicates there is a road (1 ≤ a, b ≤ n) between a village and b.

Output

Output An integer representing the new minimum distance after K road patrol attainable.

Sample Input

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

Sample Output

11

HINT

10% of the data, ≤ n-1000, K =. 1;
30% of the data, and K =. 1;
80% of the data, the number of neighboring villages each village not more than 25;
90% of the data, each village adjacent villages number no more than 150;
100% of the data, 3 ≤ n ≤ 100,000, 1 ≤ K ≤ 2.

Portal:

https://www.lydsy.com/JudgeOnline/problem.php?id=1912

Ideas:

First consider the distance traveled by side without apparently $ 2 (n-1) $.

1. $ K $ =. 1, in this case obviously two longest path plus side, the result is $ 2 (n-1) -d_1 + 1 $.

2. $ $ K = 2, in this case a long time to find the two edging paths, the result is $ 2 (n-1) -d_1 + 1-d_2 + 1 $.

But the subject requires all sides to go through, so the calculation before the second case of $ d_2 $, required after the first find the longest path, all right on the edge of these paths becomes -1.

The result of this is the result from the overlapping portions only once, it becomes twice.

However, in order to facilitate the second calculation, but also the first time seeking the longest path, with the next record through the list of paths.

这个路径是两条路径相交而成的,假设这两条路径的交点为$x$:一条是$ x $下面的最长路,另一条是$ x $下面的次长路(注意它也是包含了$ y $下面的最长路),如下图

 

 这就是代码中开始是由$s_2[] $数组索引,最后却变成由$ s_1[]$数组索引。

代码

  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 const int N = 100005;
  6 
  7 struct node
  8 {
  9     int to;
 10     int v;
 11     int nxt;
 12 };
 13 
 14 node e[N << 1];
 15 
 16 int head[N];
 17 
 18 int tot;
 19 void addedges(int u, int v)
 20 {
 21     e[++tot].to = v;
 22     e[tot].v = 1;
 23     e[tot].nxt = head[u];
 24     head[u] = tot;
 25 
 26     e[++tot].to = u;
 27     e[tot].v = 1;
 28     e[tot].nxt = head[v];
 29     head[v] = tot;
 30 }
 31 int s1[N];
 32 int s2[N];
 33 int dis;
 34 int pos;
 35 //通过找最大和次大来求直径
 36 int dfs(int x, int fa)
 37 
 38 {
 39     int fm = 0;//最大值
 40     int sm = 0;//次大值
 41 
 42     for(int i = head[x]; i; i = e[i].nxt)
 43     {
 44         int y = e[i].to;
 45         if(y == fa)
 46             continue;
 47         int v = e[i].v + dfs(y, x);
 48 
 49         if(v > fm)
 50         {
 51             sm = fm;
 52             fm = v;
 53             s2[x] = s1[x];
 54             s1[x] = i;
 55         }
 56         else if(v > sm)
 57         {
 58             sm = v;
 59             s2[x] = i;
 60         }
 61     }
 62     if(fm + sm > dis)
 63     {
 64         dis = fm + sm;
 65         pos = x;
 66     }
 67     return fm;
 68 }
 69 int main()
 70 
 71 {
 72     int n, k;
 73     scanf("%d%d", &n, &k);
 74     for(int i = 1; i < n; i++)
 75     {
 76         int a, b;
 77         scanf("%d%d", &a, &b);
 78         addedges(a, b);
 79     }
 80     int ans = 2 * (n - 1);
 81 
 82     dfs(1, 0);
 83     ans = ans - dis + 1;
 84 
 85     if(k == 2)
 86     {
 87         dis = 0;
 88         for(int i = s1[pos]; i; i = s1[e[i].to] )
 89         {
 90             e[i].v = -1;
 91         }
 92 
 93         for(int i = s2[pos]; i; i = s1[e[i].to] )//上面图片的内容
 94         {
 95             e[i].v = -1;
 96         }
 97         dfs(1, 0);
 98         ans = ans - dis + 1;
 99     }
100 
101     printf("%d\n", ans );
102 }

 

Guess you like

Origin www.cnblogs.com/yyaoling/p/12323204.html