其他分享
首页 > 其他分享> > 【APIO2010】巡逻

【APIO2010】巡逻

作者:互联网

这是一道关于树的直径的好题,值得一刷。

本题有两个难点,一个是分类讨论k,另一个是代码的实现(其实还好)。

本题k可以为1或2,因此我们分类讨论一下。

我们先进行两次bfs求出树的直径,在bfs的同时记录在直径上与每一个点的相连的边,方便之后赋值-1,之后再进行一次树形dp求出树的直径即可。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 using namespace std;
 6 inline int read() {
 7     int ret=0;
 8     int op=1;
 9     char c=getchar();
10     while(c<'0'||c>'9') {if(c=='-') op=-1; c=getchar();}
11     while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar();
12     return ret*op;
13 }
14 struct node {
15     int next,to,dis;
16 }a[100010<<1];
17 int n,head[100010<<1],num=1,k,dis[100010],pre[100010],ret,x,maxx;
18 queue<int> q;
19 inline void add(int from,int to,int dis=1) {
20     a[++num].next=head[from];
21     a[num].to=to;
22     a[num].dis=dis;
23     head[from]=num;
24 }
25 int bfs(int s) {
26     while(!q.empty()) q.pop();
27     memset(dis,0x3f,sizeof(dis));
28     dis[s]=pre[s]=0;
29     q.push(s);
30     while(!q.empty()) {
31         int now=q.front();
32         q.pop();
33         for(int i=head[now];i;i=a[i].next) {
34             int v=a[i].to;
35             if(dis[v]==0x3f3f3f3f) {
36                 dis[v]=dis[now]+a[i].dis;
37                 pre[v]=i;
38                 q.push(v);
39             }
40         }
41     }
42     int y=1;
43     for(int i=1;i<=n;i++)
44         if(dis[i]>dis[y]) y=i;
45     return y;
46 }
47 int zhijing() {
48     ret=bfs(1);
49     ret=bfs(ret);
50     return dis[ret];
51 }
52 int dp(int u,int fa) {
53     int sum1=0,sum2=0;
54     for(int i=head[u];i;i=a[i].next) {
55         int v=a[i].to;
56         if(v==fa) continue ;
57         sum2=max(sum2,dp(v,u)+a[i].dis);
58         if(sum2>sum1) swap(sum2,sum1);
59     }
60     maxx=max(maxx,sum1+sum2);
61     return sum1;
62 }
63 int main() {
64     n=read(); k=read();
65     for(int i=1;i<n;i++) {
66         int x=read(),y=read();
67         add(x,y);
68         add(y,x);
69     }
70     x=zhijing();
71     if(k==1) {
72         printf("%d\n",2*(n-1)-x+1);
73         return 0;
74     }
75     while(pre[ret]) {
76         a[pre[ret]].dis=a[pre[ret]^1].dis=-1;
77         ret=a[pre[ret]^1].to;
78     }
79     dp(1,0);
80     printf("%d\n",2*n-x-maxx);
81     return 0;
82 }
AC Code

 

标签:int,APIO2010,sum2,ret,bfs,sum1,巡逻,dis
来源: https://www.cnblogs.com/shl-blog/p/10799785.html