您的位置:首页 > 产品设计 > UI/UE

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)

代码:

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: