Terrorist’s destroy HDU - 4679

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. 

InputThe first line contains integer T(1<=T<=20), denote the number of the test cases. 
For each test cases,the first line contains a integer n(1 < n <= 100000);denote the number of the houses; 
Each of the following (n-1) lines contains third integers u,v,w, indicating there is a road between house u and houses v,and will cost terrorist w energy to destroy it.The id of these road is number from 1 to n-1.(1<=u<=n , 1<=v<=n , 1<=w<=10000)OutputFor each test case, output the case number first,and then output the id of the road which the terrorist should destroy.If the answer is not unique,output the smallest id.Sample Input

2
5
4 5 1
1 5 1
2 1 1
3 5 1
5
1 4 1
1 3 1
5 1 1
2 5 1

Sample Output

Case #1: 2
Case #2: 3 题意:给出一颗树,删除其中的一个边,随后变成了两颗树,两颗树的直径为l1和l2,剪掉的边长为x,要求x*max(l1,l2)最小,求删除的是第几条边
思路:1.剪掉的是原来树上的枝,那么就是原来树的直径*删除的那条边的长度
   2.删除的是原来树上的直径的某一条,那么肯定是直径的一部分加枝条*删除的那条变的长度
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<stack>
#include<cstdlib>
#include <vector>
#include<queue>
using namespace std;
const int INF = ;
const int maxn = ;
int q[maxn],dislong[maxn],deleteLeft[maxn],deleteRight[maxn],pre[maxn],father[maxn],dep[maxn];
int list[maxn],Next[maxn],p[maxn],c[maxn],id[maxn],maxx,n;
bool b[maxn],inlong[maxn]; int findlong(int xx,int n)
{
int t,w,now,k,x;
for (int i = ; i <= n; i++)
{
b[i] = true;
}
t = ; w = ;
q[] = xx;
dislong[] = ;
b[xx] = false;
pre[xx] = ;
maxx = ;
while (t < w)
{
t++; x = q[t];
k = list[x];
while (k > )
{
if (b[p[k]] == true)
{
w++;
b[p[k]] = false;
q[w] = p[k];
dislong[w] = dislong[t]+;
pre[p[k]] = x;
if (dislong[w] > maxx) {maxx = dislong[w]; now = p[k];}
}
k = Next[k];
}
}
return now;
}
void init(int n)
{
for (int i = ; i <= n; i++)
{
list[i] = ;
}
}
void dfs_dep(int x,int pre1)
{
int k;
dep[x] = ;
k = list[x];
while (k > )
{
if (inlong[p[k]] == false && p[k] != pre1)
{
dfs_dep(p[k],x);
dep[x] = max(dep[x],dep[p[k]]+);
}
k = Next[k];
}
} int main()
{
int t;
scanf("%d",&t);
int ca = ;
while(t--)
{
int tot = ;
scanf("%d",&n);
init(n);
for (int i = ;i < n; i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
tot++;
Next[tot] = list[u];
list[u] = tot;
p[tot] = v;
c[tot] = w;
id[tot] = i;
tot++;
Next[tot] = list[v];
list[v] = tot;
p[tot] = u;
c[tot] = w;
id[tot] = i;
}
if (n != )
{
memset(pre,,sizeof(pre));
int front = findlong(,n);
int rear = findlong(front,n);
int sum = maxx-; int k = rear;
memset(inlong,false,sizeof(inlong));
memset(father,,sizeof(father));
while (k > )
{
inlong[k] = true;
father[pre[k]] = k;
k = pre[k];
}
memset(dep,,sizeof(dep));
for(int i=;i<=n;i++)
if(inlong[i])
dfs_dep(i,);
memset(deleteLeft,,sizeof deleteLeft);
memset(deleteRight,,sizeof deleteRight);
k = front;
int step = ;
while (k != rear)
{
step++;
deleteLeft[k] = max(deleteLeft[pre[k]],step-+dep[k]-);
k = father[k];
} k = rear; step = ;
father[rear] = ;
while (k != front)
{
step++;
deleteRight[k] = max(deleteRight[father[k]],step-+dep[k]-);
k = pre[k];
}
//遍历直径
int ans = INF;
int result = INF;
k = front;
int kk;
while (k != rear)
{
kk = list[k];
while (kk > )
{
if (p[kk] == father[k]) break;
kk = Next[kk];
}
if (ans > c[kk]*max(deleteLeft[k],deleteRight[father[k]]))
{
ans = c[kk]*max(deleteLeft[k],deleteRight[father[k]]);
result = id[kk]; }
else if (ans == c[kk]*max(deleteLeft[k],deleteRight[father[k]]))
{
if (result > id[kk]) result = id[kk];
}
k = father[k];
} //遍历枝条
for (int i = ; i <= n; i++)
{
k = list[i];
while (k > )
{
if(!(inlong[i] && inlong[p[k]]))
{
if (ans > c[k]*sum)
{
ans = c[k]*sum;
result = id[k]; }
else if (ans == c[k]*sum)
{
if (result > id[k]) result = id[k];
}
}
k = Next[k];
}
}
printf("Case #%d: %d\n",ca++,result); }
}
return ;
}

网上也有思路说之间dfs直径的两个端点,但是会爆栈,要手动添栈,但在hdu上交了一发不用加栈。代码如下

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<stack>
#include<cstdlib>
#include <vector>
#include<queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = ;
struct Edge
{
int to,next;
int id,w;
}edge[maxn*];
int mm[maxn*];
int maxx[maxn],smaxx[maxn],head[maxn],tot;
int ans;
int dep[maxn];
int p[maxn];
bool used[maxn];
int cnt;
int Index;
int a[maxn];
void init()
{
memset(head,-,sizeof head);
tot = ;
} void addedge(int u,int v,int w,int id)
{
edge[tot].to = v;
edge[tot].w = w;
edge[tot].id = id;
edge[tot].next = head[u];
head[u] = tot++;
edge[tot].to = u;
edge[tot].w = w;
edge[tot].id = id;
edge[tot].next = head[v];
head[v] = tot++;
}
void dfs1(int u,int pre)
{
p[u] = pre;
dep[u] = dep[pre] + ;
for(int i = head[u]; i != -;i = edge[i].next)
{
int v = edge[i].to;
if(v==pre)continue;
dfs1(v,u);
}
}
void dfs(int u,int pre)
{
mm[u] = ;
maxx[u] = ;
smaxx[u] = ;
for(int i = head[u];i != -;i = edge[i].next)
{
int v = edge[i].to;
if(v == pre)continue;
dfs(v,u);
if(maxx[v]+ > smaxx[u])
{
smaxx[u] = maxx[v] + ;
if(smaxx[u] > maxx[u])
{
swap(smaxx[u],maxx[u]);
}
}
if(mm[v] > mm[u])
mm[u] = mm[v];
}
mm[u] = max(mm[u],maxx[u]+smaxx[u]);
}
void solve(int u,int pre)
{
for(int i = head[u];i != -;i = edge[i].next)
{
int v = edge[i].to;
int w = edge[i].w;
if(v == pre)continue;
solve(v,u);
if(used[v])
{
a[edge[i].id] = max(a[edge[i].id],w*mm[v]);
}
else
{
a[edge[i].id] = max(a[edge[i].id],w*cnt);
}
}
} int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
int n;
scanf("%d",&T);
int u,v,w;
int iCase = ;
while(T--)
{
iCase ++;
init();
scanf("%d",&n);
for(int i = ;i < n;i++)
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w,i);
}
dep[] = ;
dfs1(,);
u = ;
for(int i = ;i <= n;i++)
if(dep[u] < dep[i])
u = i;
dfs1(u,);
v = ;
for(int i =;i <= n;i++)
if(dep[v] < dep[i])
v = i;
cnt = dep[v]-;
memset(used,false,sizeof(used));
int tmp = v;
while(tmp)
{
used[tmp] = true;
tmp = p[tmp];
}
for(int i = ;i <= n;i++)
a[i] = ;
ans = INF;
dfs(u,);
solve(u,-);
dfs(v,);
solve(v,-);
for(int i = ;i < n;i++)
if(a[i]<ans)
{
ans = a[i];
Index = i;
}
printf("Case #%d: %d\n",iCase,Index);
} return ;
}

Terrorist’s destroy HDU - 4679的更多相关文章

  1. HDU 4679 Terrorist’s destroy (2013多校8 1004题 树形DP)

    Terrorist’s destroy Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

  2. hdu 4679 Terrorist’s destroy 树形DP

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4679 题意:给定一颗树,每条边有一个权值w,问切掉哪条边之后,分成的两颗树的较大的直径*切掉边的权值最小? ...

  3. HDU 4679 Terrorist’s destroy

    如果不在最长路的边,那么肯定是w*最长路. 如果在最长路,那么把最长路分成两段,左边树的最长路就是左段+左边点的次短路(不包含最长路上的点的最长路) ,右边同理. 还有就是更新,经过左端点的最长路,不 ...

  4. hdu 4679 Terrorist’s destroy 树的直径+dp

    题意:给你一棵树,每条边都有值W,然后问你去掉一条边,令val = w*max(两颗新树的直径),求val最小值~ 做法,先求树的直径,然后算出直径上每个点的最长枝条长度.这样对于每一条边,假如是枝条 ...

  5. 树形DP 2013多校8(Terrorist’s destroy HDU4679)

    题意: There is a city which is built like a tree.A terrorist wants to destroy the city's roads. But no ...

  6. HDU-4679 Terrorist’s destroy 树形DP,维护

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4679 题意:给一颗树,每个边有一个权值,要你去掉一条边权值w剩下的两颗子树中分别的最长链a,b,使得w ...

  7. hdu 4679 树状dp

    思路:我们其实只需要枚举每条边,求得最小值就行了. 先dfs算出每个节点作为根时,其子树的最长路径,以及进过该节点的最长,次长,第三长路径. 然后在次dfs枚举求出切断某条边,求出这条边的两个端点为子 ...

  8. hdu 4679 (树形DP)

    题意:给一棵树,边的权值都是1,摧毁每条边是有代价的,选择摧毁一条边,把一棵树分成两部分,求出两部分中距离最大的两点的距离,求出距离*代价最小的边,多条的话输出序号最小的. 刚开始理解错题意了,wro ...

  9. HDU 4679 String

    String Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Sub ...

随机推荐

  1. Nginx支持PHP的CI框架

    1.找到CI库的配置文件修改 $config['base_url']    = 'http://test.example.com'; $config['uri_protocol'] = 'PATH_I ...

  2. 前端js优化方案(一)

    最近在读<高性能javascript>,在这里记录一下读后的一些感受,顺便加上自己的一些理解,如果有兴趣的话可以关注的我的博客http://www.bloggeng.com/,我会不定期发 ...

  3. mysql 5.7以上安装遇到的问题

    参考地址:  https://blog.csdn.net/u012278016/article/details/80455439 本人在window上安装mysql 5.7版本以上的mysql,出现很 ...

  4. linux 下 `dirname $0`(转)

    在命令行状态下单纯执行 $ cd `dirname $0` 是毫无意义的.因为他返回当前路径的".".这个命令写在脚本文件里才有作用,他返回这个脚本文件放置的目录,并可以根据这个目 ...

  5. adc verilog spi 时序

    我用的是adc081sd芯片,(由于我们使用的是FPGA不用像单片机那样考虑极性cpol,相位cpha,下面仅仅介绍下跟单片机比较下) 什么是cpol:若cs被拉为低电平时sclk(时钟)是高那么cp ...

  6. vue系列(一)子组件和父组件

    父组件传递数据到子组件props 父组件 <template> <div class="main"> <div class="top&quo ...

  7. HDU汉诺塔系列

    这几天刷了杭电的汉诺塔一套,来写写题解. HDU1207 汉诺塔II HDU1995 汉诺塔V HDU1996 汉诺塔VI HDU1997 汉诺塔VII HDU2064 汉诺塔III HDU2077  ...

  8. 【51nod1705】七星剑(成环DP)

    点此看题面 大致题意: 你要把一把剑从0星升至7星,有n颗宝石供你选择,第i颗宝石的价值是c[i],用第i颗宝石将剑从k-1星升至k星的成功率是prob[k][i],而失败后会掉lose[k][i], ...

  9. apache的安全增强配置(使用mod_chroot,mod_security)

    apache的安全增强配置(使用mod_chroot,mod_security) 作者:windydays      2010/8/17 LAMP环境的一般入侵,大致经过sql注入,上传webshel ...

  10. datetime 插件

    1  写一段文本 <div id="nomarl-wrap"> <div class="form-group"> <label c ...