P3629 [APIO2010] 巡逻 (树的直径)

(这道题考察了求直径的两种方法......)

在原图中,每条边要经过两次,增加1条后,形成了一个环,那么环上的边只需要经过一次了(大量画图分析得),再增加一条又会形成一个环,如果这两个环有重叠,重叠部分还是要经过两次,就浪费了,所以我们先找直径(两次dfs),在直径的两个端点连一条边,就可以得到k=1的答案了,如果k=2,将环上的边权都设为-1,再在新图上用DP求新的直径(因为边权有负,要用DP),最后也就得到k=2时的答案了。

复制代码
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1e5+10;
 4 int to[N<<1],nxt[N<<1],edge[N<<1],head[N],tot;
 5 int n,k,p,q;
 6 int d[N],pre[N],L2;
 7 
 8 void add(int x,int y){
 9     nxt[++tot]=head[x];
10     head[x]=tot;
11     to[tot]=y;
12     edge[tot]=1;
13 }
14 
15 void dfs1(int u,int f){
16     if(d[u]>d[p]) p=u;
17     for(int i=head[u];i;i=nxt[i]){
18         int v=to[i];
19         if(v==f) continue;
20         d[v]=d[u]+edge[i];
22         dfs1(v,u); 
23     }
24 }
25 
26 void dfs2(int u,int f){
27     if(d[u]>d[q]) q=u;
28     for(int i=head[u];i;i=nxt[i]){
29         int v=to[i];
30         if(v==f) continue;
31         d[v]=d[u]+edge[i];
32         pre[v]=i;//记录路径
33         dfs2(v,u); 
34     }
35 }
36 
37 void update(int q,int p){
38     while(q!=p){
39         edge[pre[q]]=-1;
40         edge[pre[q]^1]=-1;//正反向边都变为-1
41         q=to[pre[q]^1]; 
42     }
43 }
44 
45 void dp(int x,int f){//树形DP求直径 
46 //d[]表示向下可以走的最远距离 
47     for(int i=head[x];i;i=nxt[i]){
48         int y=to[i];
49         if(y==f) continue;
50         dp(y,x);
51         L2=max(L2,d[y]+d[x]+edge[i]);
52         d[x]=max(d[x],d[y]+edge[i]);
53     }
54 }
55 
56 int main(){
57     cin>>n>>k;
58     tot=1;
59     for(int i=1;i<n;i++){
60         int x,y;
61         scanf("%d%d",&x,&y);
62         add(x,y);add(y,x);
63     }
64     dfs1(1,0);
65     memset(d,0,sizeof(d));
66     dfs2(p,0);
67     int ans=2*(n-1)-d[q]+1;
68     if(k==1){
69         cout<<ans<<endl;
70         return 0;
71     }
72     update(q,p);
73     memset(d,0,sizeof(d));
74     dp(1,0);
75     cout<<ans-L2+1<<endl;
76 }
复制代码

 



如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   YHXo  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示