树形dp-hdu-3721-Building Roads
题目链接:
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的更多相关文章
- HDU 3721 Building Roads (2010 Asia Tianjin Regional Contest) - from lanshui_Yang
感慨一下,区域赛的题目果然很费脑啊!!不过确实是一道不可多得的好题目!! 题目大意:给你一棵有n个节点的树,让你移动树中一条边的位置,即将这条边连接到任意两个顶点(边的大小不变),要求使得到的新树的直 ...
- fwt优化+树形DP HDU 5909
//fwt优化+树形DP HDU 5909 //见官方题解 // BestCoder Round #88 http://bestcoder.hdu.edu.cn/ #include <bits/ ...
- HDU 1815 Building roads
二分答案 + 2-SAT验证 POJ 稳过,HDU C++ 超时,G++ 550ms左右AC #include<cstdio> #include<cstring> #inclu ...
- HDU - 1054 Strategic Game(二分图最小点覆盖/树形dp)
d.一颗树,选最少的点覆盖所有边 s. 1.可以转成二分图的最小点覆盖来做.不过转换后要把匹配数除以2,这个待细看. 2.也可以用树形dp c.匈牙利算法(邻接表,用vector实现): /* 用ST ...
- 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分
树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...
- hdu 4123 树形DP+RMQ
http://acm.hdu.edu.cn/showproblem.php? pid=4123 Problem Description Bob wants to hold a race to enco ...
- HDU 4126 Genghis Khan the Conqueror 最小生成树+树形dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4126 Genghis Khan the Conqueror Time Limit: 10000/50 ...
- HDU 4123 Bob’s Race 树形dp+单调队列
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4123 Time Limit: 5000/2000 MS (Java/Others) Memory L ...
- HDU 1520 树形dp裸题
1.HDU 1520 Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> ...
- HDU 1561 树形DP入门
The more, The Better Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
随机推荐
- [shell]shell脚本统计数值大小
#! /bin/bash array=( ... ) var1= var2= ;i<=;i++)); do array[i]="$( cat /sys/bus/iio/devices/ ...
- NIO与传统IO的区别<转>
传统的socket IO中,需要为每个连接创建一个线程,当并发的连接数量非常巨大时,线程所占用的栈内存和CPU线程切换的开销将非常巨大.使用NIO,不再需要为每个线程创建单独的线程,可以用一个含有限数 ...
- JavaScrip——练习(做悬浮框)
通过HTML.CSS.JSP来实现 1.首先确定通过div嵌套来实现: 大的div里放默认显示的一层,限制其总层次高,设置超出部分隐藏 小的div里放鼠标移过去时显示的一层:3行1列的表格 1.1.什 ...
- github搭建个人博客----------绑定域名访问
首先你得有一个Github账号,没有的话去github.com注册一个账号,然后到达仓库信息填写界面: 创建仓库,如下图:(仓库名要以自己的github名作为前缀,后面的夹 .github.io) 后 ...
- oracle DataGuard 主从 踩过坑的
一.主机描述 dbprimary: 192.168.1.57 主机名称db1 dbstandby: 192.168.1.58 主机名成db2 SID: orcl 二.配置tns,配置好的文 ...
- 清除DataGridView显示的数据
一.DataGridView未绑定数据时清空数据 this.dgv_PropDemo.DataSource = null 二.DataGridView绑定数据时清空数据 DataGridView绑定了 ...
- js学习系列之-----apply和call
apply call 从字面意思就看出来,申请请,呼叫. 打个比方就是别人有什么功能,你向别人,申请 呼叫 一下,哥们拿你的功能用一下,而apply 和call就是实现这样的功能 apply 和cal ...
- loadrunner -56992
设置Run-time Settings ,network speed ,use bandwidth为 512: 回放脚本没有报错,5个并发运行场景报如下错误: vuser_init.c(12): Er ...
- 最大割(Maximum cut)
问题描述:把图中点分为两部分V1和V2,使得V1和V2之间的连边值最大.
- chrome浏览器插件推荐——Vimium 篇
Vimium 是chrome底下的一个插件,所有chrome浏览器或者是基于chrome内核的浏览器(比如我用的Vivaldi)都可以使用这个插件.它提供了大量快捷键来方便键盘党浏览网页.目前在Chr ...