P3629 [APIO2010] 巡逻
题意
加
分析
那么,对于
而对于
这时我们可以知道:
所以,我们只要给第一个环上的边
最后的答案还是很好推的,请读者自行推导。
#include<bits/stdc++.h> #define N 100005 #define rint int using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int n,k,cir1,cir2,pos,ans,tot; int d[N],fa[N],flag[N]; int Head[N],to[N<<1],Next[N<<1]; inline void add(int u,int v){to[++tot]=v,Next[tot]=Head[u],Head[u]=tot;} inline void dfs(int x,int f){ //dfs 求直径 fa[x]=f; if(d[pos]<d[x]) pos=x; for(rint i=Head[x];i;i=Next[i]){ rint y=to[i];if(y==f) continue; d[y]=d[x]+1,dfs(y,x); } } inline void dp(int x,int f){ //dp 求直径 for(rint i=Head[x];i;i=Next[i]){ rint y=to[i],z;if(y==f) continue; dp(y,x); if(flag[x]&&flag[y]) z=d[y]-1; //如果是在第一个环上的边,权值 -1 else z=d[y]+1; //否则 +1 cir2=max(cir2,d[x]+z); d[x]=max(d[x],z); } } int main(){ n=read(),k=read(); for(rint i=1;i<n;++i){ rint x=read(),y=read(); add(x,y),add(y,x); } dfs(1,0),d[pos]=0,dfs(pos,0);cir1=d[pos]; if(k==1) return printf("%d\n",((n-1)<<1)-cir1+1),0; memset(d,0,sizeof(d)); while(pos) flag[pos]=1,pos=fa[pos]; //记录第一个环上的点 dp(1,0); printf("%d\n",((n-1)<<1)-cir1-cir2+2); return 0; }
本文作者:南风未起
本文链接:https://www.cnblogs.com/jiangchen4122/p/17464602.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步