hdu 4679 Terrorist’s destroy 树形DP

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4679

题意:给定一颗树,每条边有一个权值w,问切掉哪条边之后,分成的两颗树的较大的直径*切掉边的权值最小?如果存在多条边使得结果相同,输出边id最小的

思路:

dept一次找出最深的节点,之后以最深的节点出发(rt1)dept找到树的直径(即找到rt2);将路径保存在f[]中;

之后分别从rt1/rt2进行深搜,找到以一个节点为根的树的直径,这样在每次dfs之后,可以求出每条边的一边的最值,这样两次取max之后就求出了切掉该边之后得到的结果

注:

如果改变在整棵树的直径上,需要取出以该棵树为根的树的直径maxn[0][v];否则就直接取整棵树的直径即可;

在dfs递推出以某根为子树的直径时,可能直径不过根节点所以要将子子树的直径递推到子树上;

  1 #include<bits/stdc++.h>
  2 #pragma comment(linker, "/STACK:1024000000,1024000000") //加栈
  3 using namespace std;
  4 #define rep0(i,l,r) for(int i = (l);i < (r);i++)
  5 #define rep1(i,l,r) for(int i = (l);i <= (r);i++)
  6 #define rep_0(i,r,l) for(int i = (r);i > (l);i--)
  7 #define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
  8 #define MS0(a) memset(a,0,sizeof(a))
  9 #define MS1(a) memset(a,-1,sizeof(a))
 10 #define MSi(a) memset(a,0x3f,sizeof(a))
 11 #define inf 0x3f3f3f3f
 12 #define lson l, m, rt << 1
 13 #define rson m+1, r, rt << 1|1
 14 typedef pair<int,int> PII;
 15 #define A first
 16 #define B second
 17 #define MK make_pair
 18 typedef long long ll;
 19 typedef unsigned int uint;
 20 template<typename T>
 21 void read1(T &m)
 22 {
 23     T x=0,f=1;char ch=getchar();
 24     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
 25     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
 26     m = x*f;
 27 }
 28 template<typename T>
 29 void read2(T &a,T &b){read1(a);read1(b);}
 30 template<typename T>
 31 void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
 32 template<typename T>
 33 void out(T a)
 34 {
 35     if(a>9) out(a/10);
 36     putchar(a%10+‘0‘);
 37 }
 38 #define N 100007
 39 int head[N<<1],tot;
 40 struct edge{
 41     int to,w,id,Next;
 42 }e[N<<1];
 43 void ins(int a,int b,int w,int id)
 44 {
 45     e[++tot].Next = head[a];
 46     e[tot].to = b;
 47     e[tot].w = w;
 48     e[tot].id = id;
 49     head[a] = tot;
 50 }
 51 int dep[N],p[N];
 52 void dept(int u,int pre)
 53 {
 54     p[u] = pre;
 55     dep[u] = dep[pre] + 1;
 56     for(int id = head[u];id;id = e[id].Next){
 57         int v = e[id].to;
 58         if(v == pre) continue;
 59         dept(v,u);
 60     }
 61 }
 62 int f[N],maxlen;//树的直径
 63 int aux[N];
 64 int maxn[3][N];
 65 void dfs(int u,int pre)
 66 {
 67     maxn[0][u] = maxn[1][u] = maxn[2][u] = 0;
 68     for(int id = head[u];id;id = e[id].Next){
 69         int v = e[id].to;
 70         if(v == pre) continue;
 71         dfs(v,u);
 72         if(maxn[1][u] <= maxn[1][v]+1){
 73             maxn[2][u] = maxn[1][u];
 74             maxn[1][u] = maxn[1][v]+1;
 75         }else if(maxn[2][u] < maxn[1][v]+1)
 76             maxn[2][u] = maxn[1][v]+1;
 77         if(maxn[0][u] < maxn[0][v])    //**可能树的直径不过根节点;
 78             maxn[0][u] = maxn[0][v];
 79     }
 80     maxn[0][u] = max(maxn[0][u],maxn[1][u] + maxn[2][u]);  //以u为根的子树的直径
 81 }
 82 void solve(int u,int pre)
 83 {
 84     for(int id = head[u];id;id = e[id].Next){
 85         int v = e[id].to, w = e[id].w;
 86         if(v == pre) continue;
 87         if(f[u] && f[v]){ //边在直径上
 88             aux[e[id].id] = max(aux[e[id].id],w*maxn[0][v]);
 89         }else{
 90             aux[e[id].id] = max(aux[e[id].id],w*maxlen);
 91         }
 92         solve(v,u);
 93     }
 94 }
 95 int main()
 96 {
 97     //freopen("data.txt","r",stdin);
 98     //freopen("out.txt","w",stdout);
 99     int kase = 1,T,n;
100     read1(T);
101     while(T--){
102         MS0(head);tot = 0;
103         MS0(f);
104         read1(n);
105         rep0(i,1,n){
106             int u,v,w;
107             read3(u,v,w);
108             ins(u,v,w,i);ins(v,u,w,i);
109         }
110         dep[0] = 0;
111         dept(1,0);
112         int rt1 ,rt2 ,d = 0;
113         rep1(i,1,n) if(d < dep[i]) d = dep[i],rt1 = i;
114         dept(rt1,0);
115         d = 0;
116         rep1(i,1,n) if(d < dep[i]) d = dep[i],rt2 = i;
117         maxlen = d-1; //求出树的直径;以及两端的节点标号
118         int index = rt2;
119         while(index){
120             f[index] = 1;
121             index = p[index];   //从树直径的终点递推到起点
122         }
123         MS0(aux);
124         dfs(rt1,-1);
125         solve(rt1,0);
126         dfs(rt2,-1);
127         solve(rt2,0);
128         int ans = inf;
129         rep0(i,1,n){
130             if(ans > aux[i]) ans = aux[i],index = i;
131         }
132         printf("Case #%d: %d\n",kase++,index);
133     }
134     return 0;
135 }
时间: 2024-11-05 11:05:34

hdu 4679 Terrorist’s destroy 树形DP的相关文章

HDU 4679:Terrorist’s destroy 树形DP

Terrorist’s destroy 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4679 题意: 给出一棵树,删除该树的某一条边会得到一个值a(该边的energy值)和一个值b(删除该边得到的两棵子树上的最大路径),求删除哪条边可以使得a*b最小,若存在多个最小值,则选择边号较小的那条. 树上所有相邻节点间的距离都为1. 题解: 可以知道删除某边后两棵子树的最长路径都是由原树直径的两个端点出发的,以任意一个节点为起点跑一边BFS(或者DFS

Bestcoder round #65 &amp;&amp; hdu 5593 ZYB&#39;s Tree 树形dp

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 354    Accepted Submission(s): 100 Problem Description ZYB has a tree with N nodes,now he wants you to solve the numbers of nodes distanced no m

hdu 4514 并查集+树形dp

湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 4539    Accepted Submission(s): 816 Problem Description 随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,

hdu 4118 Holiday&#39;s Accommodation 树形dp

Holiday's Accommodation Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4118 Description Nowadays, people have many ways to save money on accommodation when they are on vacation.One of these ways is exchanging

HDU 1011 Starship Troopers(树形dp+背包)

Starship Troopers Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13109    Accepted Submission(s): 3562 Problem Description You, the leader of Starship Troopers, are sent to destroy a base of

hdu 5379 Mahjong tree(树形dp)

题目链接:hdu 5379 Mahjong tree 树形dp,每个节点最多有2个子节点为一棵节点数大于1的子树的根节点,而且要么后代的节点值都大于,要么都小于本身(所以tson不为0是,要乘2).对于K个单一节点的子节点,种类数即为全排K!.当一个节点没有兄弟节点时,以这个节点为根结点的子树,根可以选择最大或者最小. #pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #inclu

HDU 5758 Explorer Bo(树形DP)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5758 [题目大意] 给出一棵树,每条路长度为1,允许从一个节点传送到任意一个节点,现在要求在传送次数尽量少的情况下至少经过每条路一遍啊,同时最小化走过的路程总长度.输出路程总长度. [题解] 首先,对于传送次数尽量少这个条件,我们很容易发现,当且仅当每次出发点和终止点都是叶节点的时候,是最少的,当然在叶节点无法两两匹配的时候,再多走一条链. 然后就是叶节点的匹配问题,使得匹配后的叶节点连线覆盖全

hdu 4003 Find Metal Mineral 树形DP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4003 Humans have discovered a kind of new metal mineral on Mars which are distributed in point‐like with paths connecting each of them which formed a tree. Now Humans launches k robots on Mars to collect

hdu 4123 Bob’s Race(树形dp+RMQ)

题目链接:hdu 4123 Bob's Race 题目大意:一个城镇有N个住户,N-1条路连接两个住户,保证N个住户联通,M次询问,给定N条边的信息,包括连 接的住户序号以及路的长度.然后是M次询问,每次询问Q,要求找到最长的连续序号,使得Max(dis[i]) - Min(dis[i]) ≤ Q(l≤i≤r),输出最大的r-l+1.dis[i]为从第i个住户出发,不重复走过路能移动的最远距离. 解题思路:树形dp,通过两次dfs,第1次处理出每个节点中孩子节点移动的最长距离和第二长距离,第2次