[题解]P3629 [APIO2010] 巡逻
\(k=1\)时,我们一定贪心选择直径\(d\)的两个端点建立道路,所以答案是\(2\times(n-1)-d+1\)。
\(k=2\)时,两条新建的道路恰好形成\(2\)个环,我们通过手玩可以发现一个结论:
- \(1\)条边恰好被经过\(1\)次,当且仅当它恰好位于\(1\)个环上。
- \(1\)条边恰好被经过\(2\)次,当且仅当它不满足上面的条件。
可以结合下图理解。
那么我们的策略就是尽可能最大化“恰好位于\(1\)个环上”的边数。
可以证明,\(k=2\)时选择直径的两个端点修路一定可以取到最优解。
我们假设\(AB\)、\(CD\)是我们选取的两条路径,而\(EF\)是直径。我们证明,对于\(AB,CD\)的所有选法,改为让\(EF\)参与一定不会让答案更劣。
- 当\(AB,CD\)没有公共边时,直接用\(EF\)代替其中一条路径即可,没有讨论的必要。
- 当\(AB,CD\)有公共边时,这一段公共部分一定是连续的(否则就有环了),将其设为\(PQ\),讨论\(EF\)的位置:
- 当\(EF\)与\(PQ\)无公共边时,如下图,选\(AB,CD\)可以用选\(FB,ED\)代替(因为\(FY\ge AY,EX\ge CX\)),而选\(FB,ED\iff\)选\(EF,BD\)。
- 当\(EF\)与\(PQ\)的一部分重合时,如下图(\(EF\)只与\(PQ\)有重合的情况没画,是同理的),\(EF\)可以代替掉\(AB,CD\)的任意一条,因为它的重合长度更短,且自身更长。
- 当\(EF\)覆盖\(PQ\)时,如下图,我们可以将选\(AB,CD\)看作选\(AD,BC\),而\(AD,BC\)可以用选\(EF,BC\)代替,因为两种选法重合部分长度相同,而\(EF\ge AD\)。根据\(EF\)覆盖的位置,这里的情况会有所不同,但是证明同理。
(其实就是感性理解啦……)
有了这个结论,我们第一条路径就可以大胆选择直径\(d\)。接下来我们考虑另一条路径\(d'\)怎么找,才能让答案最大。
我们知道\(d'\)与\(d\)每有一条边重合,答案都相较\(2\times(n-1)-d+1\)增加了\(1\);每有一条边不重合,答案都相较\(2\times(n-1)-d+1\)减少了\(1\)。
所以我们可以先跑一遍直径\(d\),然后把直径上的边权值都设为\(-1\),再跑一遍直径\(d'\),答案即为\(2\times(n-1)-d-d'+2\)。
第\(1\)次求直径无负权边,且需要记录路径,所以使用两次DFS;第\(2\)次有负权边,不需要记录路径,所以使用树形DP。
时间复杂度\(O(n)\)。
点击查看代码
#include<bits/stdc++.h> #define int long long #define N 100010 using namespace std; int n,k,d[N],cur,pre[N],f[N],dis; bool flg; bitset<N> vis; vector<int> G[N]; void dfs(int u,int fa){ for(int i:G[u]){ if(i==fa) continue; d[i]=d[u]+1; if(d[i]>d[cur]) cur=i; dfs(i,u); } if(flg) pre[u]=fa; } void dfs2(int u,int fa){ for(int i:G[u]){ if(i==fa) continue; int w=(vis[u]&&vis[i]?-1:1); dfs2(i,u); dis=max(dis,f[u]+f[i]+w); f[u]=max(f[u],f[i]+w); } } signed main(){ ios::sync_with_stdio(false); cin.tie(nullptr),cout.tie(nullptr); cin>>n>>k; for(int i=1,u,v;i<n;i++){ cin>>u>>v; G[u].emplace_back(v); G[v].emplace_back(u); } dfs(1,0),d[cur]=0,flg=1,dfs(cur,0); if(k==1){ cout<<2*(n-1)-d[cur]+1<<"\n"; return 0; } for(int i=cur;i;i=pre[i]) vis[i]=1; dfs2(1,0); cout<<2*(n-1)-d[cur]-dis+2<<"\n"; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效