1912: [Apio2010]patrol 巡逻
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 1186 Solved: 644
[ Submit][ Status][ Discuss]
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
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。
Source
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 2E5 + 20;
struct E{
int to,va;
E(){}
E(int to,int va): to(to),va(va){}
}edgs[maxn];
int n,k,cnt,ma,from[maxn],dis[maxn];
bool vis[maxn];
vector <int> v[maxn];
queue <int> Q;
void BFS(int now)
{
memset(vis,0,sizeof(vis));
vis[now] = 1;
dis[now] = 0;
Q.push(now);
while (!Q.empty()) {
int x = Q.front(); Q.pop();
for (int i = 0; i < v[x].size(); i++) {
int to = edgs[v[x][i]].to;
if (vis[to]) continue;
vis[to] = 1;
dis[to] = dis[x] + edgs[v[x][i]].va;
Q.push(to);
from[to] = v[x][i];
}
}
}
int getint()
{
char ch = getchar();
int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret*10 + ch - '0',ch = getchar();
return ret;
}
int Dfs(int x,int fa)
{
int A,B; A = B = 0;
for (int i = 0; i < v[x].size(); i++) {
int to = edgs[v[x][i]].to;
if (to == fa) continue;
int Now = edgs[v[x][i]].va + Dfs(to,x);
if (Now > A) B = A,A = Now;
else if (Now > B) B = Now;
}
ma = max(ma,A + B);
return A;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
n = getint();
k = getint();
int Ans = 2*(n-1);
for (int i = 1; i < n; i++) {
int x,y;
x = getint();
y = getint();
v[x].push_back(cnt);
edgs[cnt++] = E(y,1);
v[y].push_back(cnt);
edgs[cnt++] = E(x,1);
}
BFS(n/2);
int Max = 0,s,t;
for (int i = 1; i <= n; i++)
if (dis[i] > Max)
Max = dis[i],s = i;
BFS(s);
Max = 0;
for (int i = 1; i <= n; i++)
if (dis[i] > Max)
Max = dis[i],t = i;
Ans = Ans - Max + 1;
if (k == 1) {
cout << Ans;
return 0;
}
for (int i = t; i != s; i = edgs[from[i]^1].to) {
edgs[from[i]].va = -1;
edgs[from[i]^1].va = -1;
}
Dfs(n/2,0);
Ans -= ma;
cout << Ans + 1;
return 0;
}