树形DP 2013多校8(Terrorist’s destroy HDU4679)
来源:互联网 发布:setscale java 编辑:程序博客网 时间:2024/06/08 13:05
题意:
There is a city which is built like a tree.A terrorist wants to destroy the city's roads. But now he is alone, he can only destroy one road, then the city will be divided into two cities. Impression of the city is a number defined as the distance between the farthest two houses (As it relates to the fare).When the terrorist destroyed a road, he needs to spend some energy, assuming that the number is a.At the same time,he will get a number b which is maximum of the Impression of two cities. The terrorist wants to know which road to destroy so that the product of a and b will be minimized.You should find the road's id.
Note that the length of each road is one.
Note that the length of each road is one.
给出一个树形图,和边权值w代表耗费的能量,每条边的长度是1;破坏一条边<u,v>会形成两棵树,b是两个树中较大的那个直径,a是<u,v>的能量值,求破坏哪条边保证a*b的至最小若存在多个,则输出最先出现的那条边;
分析:求树的直径,我们很容易想到两个dfs可以求出树的直径,所以先树形dp(前两个dfs)求出每个点的正向距离的最大值dis[u][0]和次大值dis[u][1],以及反向距离最大值dis[u][2],然后第三个dfs深搜枚举每条边的两个点<u,v>,对于v点,v所对应的子树的直径就是
对于v如果belong[u]==v这u所对应的子树的直径是dis[u][1]+dis[u][2];否则对应的子树直径是dis[u][0]+dis[u][2];
dis[v][0]+dis[v][1];
对于v如果belong[u]==v这u所对应的子树的直径是dis[u][1]+dis[u][2];否则对应的子树直径是dis[u][0]+dis[u][2];
然后枚举a*b即可:
#pragma comment(linker, "/STACK:1024000000,1024000000")#include"stdio.h"#include"string.h"#include"stdlib.h"#include"queue"#include"algorithm"#include"string.h"#include"string"#include"math.h"#include"vector"#include"stack"#include"map"#define eps 1e-4#define inf 0x3f3f3f3f#define M 100009#define PI acos(-1.0)using namespace std;struct node{ int u,v,w,next;}edge[M*2];int t,head[M],dis[M][4],length[M*2],belong[M];__int64 ans,num[M],n;void init(){ t=0; memset(head,-1,sizeof(head));}void add(int u,int v,int w){ edge[t].u=u; edge[t].v=v; edge[t].w=w; edge[t].next=head[u]; head[u]=t++;}void dfs(int u,int f){ dis[u][0]=dis[u][1]=dis[u][2]=0; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].v; if(v==f)continue; dfs(v,u); if(dis[u][0]<dis[v][0]+1) { dis[u][1]=dis[u][0]; dis[u][0]=dis[v][0]+1; belong[u]=v; } else if(dis[u][1]<dis[v][0]+1) dis[u][1]=dis[v][0]+1; }}void dfs1(int u,int f){ for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==f) continue; if(belong[u]==v) dis[v][2]=max(dis[u][1],dis[u][2])+1; else dis[v][2]=max(dis[u][0],dis[u][2])+1; dfs1(v,u); }}void dfs2(int u,int f){ for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].v; if(v==f)continue; if(belong[u]==v) { length[i]=dis[v][0]+dis[v][1]; length[i^1]=dis[u][1]+dis[u][2]; } else { length[i]=dis[v][0]+dis[v][1]; length[i^1]=dis[u][0]+dis[u][2]; } dfs2(v,u); }}int main(){ int Case,i,n,a,b,c,kk=1; scanf("%d",&Case); while(Case--) { scanf("%d",&n); init(); for(i=1;i<n;i++) { scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); } dfs(1,-1); dfs1(1,-1); dfs2(1,-1); ans=inf; int id; for(i=0;i<t;i+=2) { //printf("%d %d %d %d\n",edge[i].u,edge[i].v,length[i],length[i^1]); int m=max(length[i],length[i^1])*edge[i].w; if(ans>m) { id=i; ans=m; } } printf("Case #%d: %d\n",kk++,(id+2)/2); }}
0 0
- 树形DP 2013多校8(Terrorist’s destroy HDU4679)
- hdu4679 Terrorist’s destroy(树形dp)
- HDU 4679 Terrorist’s destroy(树形dp | 多校8)
- hdu4679 Terrorist’s destroy 解题报告
- hdu 4679 Terrorist’s destroy (树形dp)
- hdu 4679 Terrorist’s destroy(树形dp)
- HDU 4679 Terrorist’s destroy (树形DP)
- hdu 4679 Terrorist’s destroy ( 树形dp 树的直径 )
- hdu 4679 Terrorist’s destroy 树形dp水题 (2013多校联合)
- 【解题报告】HDU 4679 Terrorist’s destroy -- 树形dp 删一边求两子树直径
- 2013多校联合8 1004 Terrorist’s destroy(hdu 4679)
- HDU 4679 Terrorist’s destroy
- HDU 4679 Terrorist’s destroy
- HDU 4679 Terrorist’s destroy
- hdu 4679 Terrorist’s destroy
- hdu-4679-Terrorist’s destroy
- hdu 4679Terrorist’s destroy
- HDU 4679 Terrorist’s destroy
- linux 启动流程与文件系统管理
- 求连续子数组的最大乘积
- 欧拉环、欧拉路径的判定和求法
- HomeHttp 是一个免费的网站反向代理服务
- accept是又产生一个Socket端口吗?
- 树形DP 2013多校8(Terrorist’s destroy HDU4679)
- 浅析Buffer Cache
- CF - 246 - B. Increase and Decrease(贪心)
- Poj 3254 Corn Fields(状态压缩)
- 卡片式UI的总结 android
- 第十一周项目6 (4)输入一个数,输出这个数以内的所有回文素数
- 第一天
- 不确定水平滚动条的循环滚动的实现。
- HDU1824-Let's go home(2-SAT)