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 ...
随机推荐
- css中 repeat-x 的简单用法
问repeat-x 00 中: 0 0 是 什么意思,如果改为0 -50呢,不写话默认是什么(不写话和0 0 的效果不一样)- ------<html><head><s ...
- Ecshop如何解决Deprecated: preg_replace()报错
今天安装Ecshop后,运行出现各种问题,其中 Deprecated: preg_replace() 之类的报错最多,下面贴出解决方案: 错误原因: preg_replace() 函数中用到的修饰符 ...
- Windows、Unix、Mac不同操作系统的换行问题-剖析回车符\r和换行符\n
转载链接:http://blog.csdn.net/tskyfree/article/details/8121951 一.概念: 换行符‘\n’和回车符‘\r’ (1)换行符就是另起一行 --- ' ...
- HttpURLConnection(http 1.1) 用法、状态码、状态描述
最近研究了java的HttpURLConnection的用法, 这里简单的做一下记录: Java中可以使用HttpURLConnection来请求WEB资源. 1. URL请求的类别 分为二类,GET ...
- /opt/metasploit/msf3
启动msf终端 cd /opt/metasploit/msf3 msfconsole
- python3爬虫03(find_all用法等)
#read1.html文件# <html><head><title>The Dormouse's story</title></head># ...
- RF的一些技术知识
1. dBm 定义的是 miliwatt(毫瓦特).0 dBm=1mw: dBw 定义 watt.0 dBW = 1 W =1000 mw = 10lg(1000/1)dBm=30dbm. dB ...
- pta 编程题21 公路村村通
其它pta数据结构编程题请参见:pta 题目 这道题考察最小生成树问题,用的是Prim算法. 和Dijkstra算法相比,没有了collect数组,因为dist[v] == 0就代表v被已收录. #i ...
- java核心技术 要点笔记2
第4章 对象和类 1.面向对象 类:构造对象的模板,创建类的实例:由类构造对象的过程,封装,继承: 对象:对象的特性——对象的行为,对象的状态,对象的标识: 类之间的关系: 依赖(“user-a” ...
- IOS NSKeyedArchiver(归档存取数据)
如果对象是NSString.NSDictionary.NSArray.NSData.NSNumber等类 型,可以直接用NSKeyedArchiver进行归档和恢复 不是所有的对象都可以直接用这种方法 ...