hdu 3721 uvalive 5026 building roads
2011-09-25 20:11
501 查看
首先,我们证明一个结论:树的重心一定在树的直径上
树的直径指树上最长的一条路径,树的重心指树上所有点中到其余点最远距离最小的点
假设重心u不在直径上,那么它到距它最远点(x)的路径一定会和树的直径有交点v,否则这条路径会是新的直径的一部分,那么v到x的距离一定更小,所以重心一定在直径上
显然,我们需要移走直径上的一条边,并且移走这条边后,原来的树变成了两棵树(特殊情况是移走和叶子相连的一条边,但不影响)
那这样子,这两棵树,每棵树都有自己的直径d1,d2,那么将两棵树重新合并后,当前最优解tmp>=max(d1,d2)
我们在树1中和树2中分别找重心,新合并的树上任意点到最远点距离的最小值也可能是是树1中的重心的相对应的值x+树2中的重心相对应的值y+枚举的边长w
即tmp=max(tmp,w+x+y)
代码:
树的直径指树上最长的一条路径,树的重心指树上所有点中到其余点最远距离最小的点
假设重心u不在直径上,那么它到距它最远点(x)的路径一定会和树的直径有交点v,否则这条路径会是新的直径的一部分,那么v到x的距离一定更小,所以重心一定在直径上
显然,我们需要移走直径上的一条边,并且移走这条边后,原来的树变成了两棵树(特殊情况是移走和叶子相连的一条边,但不影响)
那这样子,这两棵树,每棵树都有自己的直径d1,d2,那么将两棵树重新合并后,当前最优解tmp>=max(d1,d2)
我们在树1中和树2中分别找重心,新合并的树上任意点到最远点距离的最小值也可能是是树1中的重心的相对应的值x+树2中的重心相对应的值y+枚举的边长w
即tmp=max(tmp,w+x+y)
代码:
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #include<stack> #include<queue> #include<vector> #include<map> #include<ctime> using namespace std; const int MAX=2555; struct node { int v,w,next,flag; }g[MAX*10]; int adj[MAX],e,n,m,dis[MAX],pre[MAX],D,tot,tmp[MAX],res[MAX]; void add(int u,int v,int w) { g[e].v=v; g[e].w=w; g[e].flag=1; g[e].next=adj[u]; adj[u]=e++; } void dfs(int u,int fa,int w,int id) { int i,v; pre[u]=id; dis[u]=w; D=max(D,w); for(i=adj[u];i!=-1;i=g[i].next) { v=g[i].v; if(v==fa||!g[i].flag) continue; dfs(v,u,w+g[i].w,i); } } void find(int root) { memset(dis,0,sizeof(dis)); dfs(root,-1,0,-1); int ma=-1,i,j; for(i=1;i<=n;i++) if(dis[i]>ma) { ma=dis[i]; j=i; } memset(dis,0,sizeof(dis)); D=-1; dfs(j,-1,0,-1); } void find_path(int t,int res[],int &tot) { int i; tot=0; for(i=pre[t];i!=-1;i=pre[g[i^1].v]) { res[tot++]=i; } } void solve() { int ans,i,j,x,y,k; find(1); ans=1<<30; for(i=1;i<=n;i++) { if(dis[i]==D) { find_path(i,res,tot); break; } } //cout<<"tot="<<tot<<endl; for(i=0;i<tot;i++) { //cout<<g[res[i]].v<<endl; g[res[i]].flag=0; g[res[i]^1].flag=0; find(g[res[i]].v); int d1=D,n1,n2; for(j=1;j<=n;j++) { if(dis[j]==D) { find_path(j,tmp,n1); break; } } if(d1==0) x=0; else x=1<<30; for(j=0;j<n1;j++) { k=g[tmp[j]].v; x=min(x,max(dis[k],D-dis[k])); k=g[tmp[j]^1].v; x=min(x,max(dis[k],D-dis[k])); } find(g[res[i]^1].v); int d2=D; for(j=1;j<=n;j++) { if(dis[j]==D) { find_path(j,tmp,n2); break; } } if(d2==0) y=0; else y=1<<30; for(j=0;j<n2;j++) { k=g[tmp[j]].v; y=min(y,max(dis[k],D-dis[k])); k=g[tmp[j]^1].v; y=min(y,max(dis[k],D-dis[k])); } g[res[i]].flag=1; g[res[i]^1].flag=1; d1=max(d1,d2); d1=max(d1,g[res[i]].w+x+y); ans=min(ans,d1); } printf("%d\n",ans); } int main() { int i,j,k,w,T; scanf("%d",&T); for(int ca=1;ca<=T;ca++) { memset(adj,-1,sizeof(adj)); e=0; scanf("%d",&n); for(i=1;i<n;i++) { scanf("%d%d%d",&j,&k,&w); j++; k++; add(j,k,w); add(k,j,w); } printf("Case %d: ",ca); solve(); } return 0; }
相关文章推荐
- UvaLive 5026 Building Roads
- UVALive 5135 HDU 3844 Mining Your Own Business
- HDU1642 UVA167 UVALive5227 The Sultan's Successors题解
- HDU 1890 UVaLive 3961 - Robotic Sort (Splay)
- UVALive 4244 Party Party Party(HDU 2779 && Sicily 1663)
- HDU1012 POJ1517 ZOJ1113 UVALive2083 u Calculate e【水题】
- UVALive 5004 Balanced Number && hdu-3967 Zero's Number(数位dp)
- 树形dp-hdu-3721-Building Roads
- HDU1014 POJ1597 UVALive5492 UVA408 ZOJ1314 Uniform Generator【随机函数+水题】
- HDU 1551 Cable master / UVALive 2452 Cable master(切电缆,二分)
- 小比赛(POJ 2992,UVALive 4108,POJ 2263,POJ 3617,HDU 5305,POJ 1988,POJ 1679,POJ 3481)
- POJ 3342 Party at Hali-Bula / HDU 2412 Party at Hali-Bula / UVAlive 3794 Party at Hali-Bula / UVA 1220 Party at Hali-Bula(树型动态规划)
- HDU 5631 Rikka with Graph / UVALive - 7240 Minimum Cut-Cut(删边操作,BestCoder)
- 伸展树模板(BZOJ 1500,UVALive 3961 HDU 1890)
- UVALIVE 2675 Peals (POJ 1260 HDU 1300)
- uvalive 5008 hdu 3717 double maze 四维bfs(好题)
- HDU 3721 Building Roads (2010 Asia Tianjin Regional Contest) - from lanshui_Yang
- UVALive 4839 HDU 3686 Traffic Real Time Query System
- POJ 1087 A Plug for UNIX / HDU 1526 A Plug for UNIX / ZOJ 1157 A Plug for UNIX / UVA 753 A Plug for UNIX / UVAlive 5418 A Plug for UNIX / SCU 1671 A Plug for UNIX (网络流)
- HDU 3721 Building Roads 树形dp + 枚举直径