https://www.lydsy.com/JudgeOnline/problem.php?id=4890php
https://www.luogu.org/problemnew/show/P3761node
从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工做。这个地区一共有n座城市,n-1条高速公路,保证了任意两运城市之间均可以经过高速公路相互可达,可是经过一条高速公路须要收取必定的交通费用。ios
小明对这个地区深刻研究后,以为这个地区的交通费用太贵。小明想完全改造这个地区,可是因为上司给他的资源有限,于是小明如今只能对一条高速公路进行改造,改造的方式就是去掉一条高速公路,而且从新修建一条同样的高速公路(即交通费用同样),使得这个地区的两个城市之间的最大交通费用最小(即便得交通费用最大的两座城市之间的交通费用最小),而且保证修建完以后任意两座城市相互可达。若是你是小明,你怎么解决这个问题?git
前置技能:树直径,树半径(代码的树半径是我本身yy的请无视orz)spa
复杂度显然是$O(n^2)$的,这就使咱们支持枚举每条边求出答案。code
设拆完路以后的两棵树为$A,B$,那么就有三种状况:blog
最长路在$A$中资源
最长路在$B$中get
最长路端点分别在$A,B$中博客
前二者求树直径便可,至于最后一个咱们就须要考虑一个问题,到底要把边加在哪里才能使这种状况的长度最小。
显然是要加在树半径最小的两个点上(懒得证了)。
因而切了(顺便复习了怎么求树直径和半径,我以为我多半是废了基本技能都不会了。)
#include<map> #include<cmath> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<vector> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=5005; const int INF=1e9; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct node{ int w,to,nxt; }e[N*2]; int n,cnt,head[N],f[N][3]; bool vis[N]; inline void add(int u,int v,int w){ e[++cnt].to=v;e[cnt].w=w;e[cnt].nxt=head[u];head[u]=cnt; } int ans; void dfs1(int u,int fa){ for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to,w=e[i].w; if(vis[v]||fa==v)continue; dfs1(v,u); if(f[u][0]<f[v][0]+w){ f[u][1]=f[u][0]; f[u][0]=f[v][0]+w; }else if(f[u][1]<f[v][0]+w) f[u][1]=f[v][0]+w; } ans=max(ans,f[u][0]+f[u][1]); } void dfs2(int u,int fa){ for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to,w=e[i].w; if(vis[v]||fa==v)continue; f[v][2]=f[u][2]+w; if(f[u][0]-w!=f[v][0])f[v][2]=max(f[v][2],f[u][0]+w); else f[v][2]=max(f[v][2],f[u][1]+w); dfs2(v,u); } ans=min(ans,max(f[u][0],f[u][2])); } int main(){ n=read(); for(int i=1;i<n;i++){ int u=read(),v=read(),w=read(); add(u,v,w);add(v,u,w); } int sum=INF; for(int i=1;i<=cnt;i+=2){ int u=e[i].to,v=e[i+1].to,w=e[i].w; int w1,w2,tmp=0; vis[v]=1; memset(f,0,sizeof(f)); ans=0;dfs1(u,0);tmp=max(tmp,ans); ans=INF;dfs2(u,0);w1=ans; vis[v]=0;vis[u]=1; ans=0;dfs1(v,0);tmp=max(tmp,ans); ans=INF;dfs2(v,0);w2=ans; vis[u]=0; tmp=max(tmp,w1+w2+w); sum=min(sum,tmp); } printf("%d\n",sum); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文做者:luyouqi233。 +
+欢迎访问个人博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++