Terrorist’s destroy HDU - 4679
Terrorist’s destroy HDU - 4679
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的更多相关文章
- 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 ...
- hdu 4679 Terrorist’s destroy 树形DP
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4679 题意:给定一颗树,每条边有一个权值w,问切掉哪条边之后,分成的两颗树的较大的直径*切掉边的权值最小? ...
- HDU 4679 Terrorist’s destroy
如果不在最长路的边,那么肯定是w*最长路. 如果在最长路,那么把最长路分成两段,左边树的最长路就是左段+左边点的次短路(不包含最长路上的点的最长路) ,右边同理. 还有就是更新,经过左端点的最长路,不 ...
- hdu 4679 Terrorist’s destroy 树的直径+dp
题意:给你一棵树,每条边都有值W,然后问你去掉一条边,令val = w*max(两颗新树的直径),求val最小值~ 做法,先求树的直径,然后算出直径上每个点的最长枝条长度.这样对于每一条边,假如是枝条 ...
- 树形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 ...
- HDU-4679 Terrorist’s destroy 树形DP,维护
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4679 题意:给一颗树,每个边有一个权值,要你去掉一条边权值w剩下的两颗子树中分别的最长链a,b,使得w ...
- hdu 4679 树状dp
思路:我们其实只需要枚举每条边,求得最小值就行了. 先dfs算出每个节点作为根时,其子树的最长路径,以及进过该节点的最长,次长,第三长路径. 然后在次dfs枚举求出切断某条边,求出这条边的两个端点为子 ...
- hdu 4679 (树形DP)
题意:给一棵树,边的权值都是1,摧毁每条边是有代价的,选择摧毁一条边,把一棵树分成两部分,求出两部分中距离最大的两点的距离,求出距离*代价最小的边,多条的话输出序号最小的. 刚开始理解错题意了,wro ...
- HDU 4679 String
String Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Sub ...
随机推荐
- Docker创建Centos踩出来的坑
屁话不多说,先来一遍正常的流程 1.下载centos镜像 # docker pull centos 2.运行容器,修改镜像 2.1 运行 # docker run -itd --name centos ...
- Unity GL 画圆
Unity下GL没有画圆的函数,只能自己来了. 如果能帮到大家,我也很高兴. 虽然没有画圆的函数,但是能画直线,利用这一点,配合微积分什么的,就可以画出来了.反正就是花很多连在一起的直线,每条直线足够 ...
- java打印堆栈信息
StackTraceElement[] stackElements = new Throwable().getStackTrace(); if(stackElements != null){ for( ...
- js和JQuery中offset等属性对比
HTML: 内容在滚动条下面 <div id="outerDiv"> <div id="myDiv" class="myDiv&qu ...
- WebAPI创建
一.创建Web API 1.Create a New Web API Project创建新的Web API项目 Start by running Visual Studio 2010 and sele ...
- C 碎片四 流程控制
前面介绍了程序中用到的一些基本要素(常量,变量,运算符,表达式),他们是构成程序的基本成分,下面将介绍C语言中流程控制的三种结构:顺序结构.分支结构.循环结构 一.顺序结构 顺序结构的程序设计是最简单 ...
- jquery 的extend的方法
用flot.js 用到了jquery的extend 方法 关于extend方法 我就照手册打一遍,加深一下理解,说实话其实我理解的也不透 extend 用一个或多个其他对象来扩展一个对象,返回被扩 ...
- Cloneable接口的作用
Cloneable接口是一个[标记接口],就是没有任何内容 implements Cloneable表示该对象能被克隆,能使用Object.clone()方法.如果没有implements Clone ...
- pat乙级1045
从左到右扫描时记录扫描到当前下标为止的最大值,如果当前元素大于这个最大值,那么它就大于它左边的所有值.同理,从右到左扫描记录扫描到当前下标为止的最小值,如果当前元素小于这个最大小值,那么它就小于它右边 ...
- Android(java)学习笔记89:Bundle和Intent类使用和交互
1. Bundle 和 Intent: Bundle只是一个信息的载体 将内部的内容以键值对组织 ,Intent负责Activity之间的交互自己是带有一个Bundle的.Intent.putE ...