题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3721

题目意思:

给一颗树,求移动一条边(边权值不变)到另外的位置,还是一棵树。求最小的树的直径。

解题思路:

充分利用树的直径的性质。

任何点的最远距离一定是树直径上的一个端点。

枚举每条边,分成两颗子树后,求出两颗子树的直径d1,d2,以及两颗树的任意点A的最大距离的最小值p1,p2.显然由树的直径的性质,知点A一定在树的直径上。

ans=min(ans,max(max(d1,d2),p1+p2+len)).

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; #define Maxn 3000
int cnt;
struct Edge
{
int v,len;
struct Edge * next;
}edge[Maxn<<1],*head[Maxn<<1]; void add(int a,int b,int len)
{
++cnt;
edge[cnt].v=b,edge[cnt].len=len;
edge[cnt].next=head[a];
head[a]=&edge[cnt];
}
int ma[Maxn],mi[Maxn];
int Max,Min; void dfs1(int cur,int fa)
{
ma[cur]=mi[cur]=0; struct Edge * p=head[cur];
while(p)
{
int v=p->v; if(v!=fa)
{
dfs1(v,cur);
if(p->len+ma[v]>ma[cur])
{
mi[cur]=ma[cur];
ma[cur]=p->len+ma[v];
}
else if(p->len+ma[v]>mi[cur])
mi[cur]=p->len+ma[v];
}
p=p->next;
}
}
void dfs2(int cur,int fa)
{
if(ma[cur]>Max)
Max=ma[cur];
if(ma[cur]<Min)
Min=ma[cur]; struct Edge * p=head[cur];
while(p)
{
int v=p->v; if(v!=fa)
{
if(p->len+ma[v]<ma[cur]) //最大距离不是从这个儿子过来的
ma[v]=p->len+ma[cur];
else if(p->len+mi[cur]>ma[v]) //最大距离就是这个儿子过来的
ma[v]=p->len+mi[cur];
else if(p->len+mi[cur]>mi[v])
mi[v]=p->len+mi[cur];
dfs2(v,cur);
}
p=p->next;
}
} int main()
{
int t,n; scanf("%d",&t);
for(int ca=1;ca<=t;ca++)
{
scanf("%d",&n); cnt=0;
memset(head,NULL,sizeof(head)); for(int i=1;i<n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
int ans=INF; //printf("%d\n",cnt);
for(int i=1;i<=cnt;i+=2)
{ //相邻两个编号为一条边
int u=edge[i].v,v=edge[i+1].v,len=edge[i].len;//枚举每一条边
int temp1,temp2; //printf("u:%d v:%d\n",u,v);
Max=0,Min=INF; //Max表示树的直径,Min表示最大距离的最小值
dfs1(u,v);dfs2(u,v); len+=Min;
temp1=Max; Max=0,Min=INF;
dfs1(v,u),dfs2(v,u); //另外一颗子树
//printf(":%d %d\n",Min,Max);
len+=Min;
temp2=Max; len=max(max(temp1,temp2),len);
if(len<ans)
ans=len;
//system("pause");
}
printf("Case %d: %d\n",ca,ans); }
return 0;
}

树形dp-hdu-3721-Building Roads的更多相关文章

  1. HDU 3721 Building Roads (2010 Asia Tianjin Regional Contest) - from lanshui_Yang

    感慨一下,区域赛的题目果然很费脑啊!!不过确实是一道不可多得的好题目!! 题目大意:给你一棵有n个节点的树,让你移动树中一条边的位置,即将这条边连接到任意两个顶点(边的大小不变),要求使得到的新树的直 ...

  2. fwt优化+树形DP HDU 5909

    //fwt优化+树形DP HDU 5909 //见官方题解 // BestCoder Round #88 http://bestcoder.hdu.edu.cn/ #include <bits/ ...

  3. HDU 1815 Building roads

    二分答案 + 2-SAT验证 POJ 稳过,HDU C++ 超时,G++ 550ms左右AC #include<cstdio> #include<cstring> #inclu ...

  4. HDU - 1054 Strategic Game(二分图最小点覆盖/树形dp)

    d.一颗树,选最少的点覆盖所有边 s. 1.可以转成二分图的最小点覆盖来做.不过转换后要把匹配数除以2,这个待细看. 2.也可以用树形dp c.匈牙利算法(邻接表,用vector实现): /* 用ST ...

  5. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  6. hdu 4123 树形DP+RMQ

    http://acm.hdu.edu.cn/showproblem.php? pid=4123 Problem Description Bob wants to hold a race to enco ...

  7. HDU 4126 Genghis Khan the Conqueror 最小生成树+树形dp

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4126 Genghis Khan the Conqueror Time Limit: 10000/50 ...

  8. HDU 4123 Bob’s Race 树形dp+单调队列

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4123 Time Limit: 5000/2000 MS (Java/Others) Memory L ...

  9. HDU 1520 树形dp裸题

    1.HDU 1520  Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> ...

  10. HDU 1561 树形DP入门

    The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

随机推荐

  1. 【WPF】ListBox使用UserContrl作为子控件,引入UserContrl界面

    <ListBox x:Name="housePlansLB" Margin="0" ItemsSource="{Binding HousePla ...

  2. Wireshark 分析捕获的数据记录

    使用 Wireshark 选取你要抓包的网络接口,并设置你的过滤器之后,当有数据通信后即可抓到对应的数据包,这里将分析其每一帧数据包的结构. 每一帧数据都有类似的结构组成,我这里使用抓到一个对应的pi ...

  3. linux实现防止恶意扫描 PortSentry

    linux实现防止恶意扫描 PortSentry   脚本 open 摘要: 端口做为服务器的大门安全很重要,当服务器运行很多服务时并向外提供服务,为防止有人恶意侦测服务器用途,可使用portsent ...

  4. awk多列匹配

    1.1.1 awk多列匹配 [hadoop@st1 data]$ netstat -an|awk  '$1~/tcp/&&$3~/64/{print $0}' tcp        0 ...

  5. e654. 获得文本的缩略图

    Shape getTextShape(Graphics2D g2d, String str, Font font) { FontRenderContext frc = g2d.getFontRende ...

  6. 您可以从 Windows 命令行上运行 gcc、g++、ar、ranlib、dlltool 和其他一些 GNU 工具

    Windows 上的安装为了在 Windows 上安装 GCC,您需要安装 MinGW.为了安装 MinGW,请访问 MinGW 的主页 www.mingw.org,进入 MinGW 下载页面,下载最 ...

  7. php -- 取日期

    1.获取当前时间方法date()很简单,这就是获取时间的方法, 格式为:date($format, $timestamp), format为格式 - 必需 timestamp为时间戳–可填参数. 比如 ...

  8. perl 利用管道读取压缩文件内容

    perl的文件句柄不仅支持普通文件, 还支持管道,今天需要统计一个fastq文件中的序列数和碱基数,而NGS的fastq文件一般都是gzip压缩的,所以 需要读取压缩文件中的内容,代码如下: my ( ...

  9. python中使用@property

    class Student(object): @property def score(self): return self._score @score.setter def score(self, v ...

  10. mysql 中查看指定表的字段名 (可根据字段变量生成c#后台代码)

    select DISTINCT data_type  from COLUMNS where table_name='表名' 用ConCat();构造生成代码.....