HDU 4679 Terrorist’s destroy
如果不在最长路的边,那么肯定是w*最长路。
如果在最长路,那么把最长路分成两段,左边树的最长路就是左段+左边点的次短路(不包含最长路上的点的最长路) ,右边同理。
还有就是更新,经过左端点的最长路,不一定是整颗左边树的最长路,乱搞一下就可以了。我是搞成一条链,写的很麻烦。。从一点搞到了快四点。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
#define INF 1000000
struct node
{
int u,v,w,next,id;
} edge[];
int t,n,first[],flag[];
int d[],in[],pre[];
int pre1[];
int pre2[];
int sp1[];
int sp2[];
int sp3[];
int sp4[];
int dp[];
int qu[];
int qv[];
int qw[];
void CL()
{
int i;
for(i = ; i <= n; i ++)
{
first[i] = -;
flag[i] = ;
dp[i] = ;
}
t = ;
}
void add(int u,int v,int w,int id)
{
edge[t].u = u;
edge[t].v = v;
edge[t].w = w;
edge[t].next = first[u];
edge[t].id = id;
first[u] = t ++;
}
void dfs(int x)
{
int i,maxz,v;
in[x] = ;
maxz = ;
for(i = first[x]; i != -; i = edge[i].next)
{
v = edge[i].v;
if(flag[v]||in[v]) continue;
in[v] = ;
dfs(v);
maxz = dp[v] + ;
}
dp[x] = maxz;
return;
}
int spfa(int x)
{
int u,v,i;
for(i = ; i <= n; i ++)
{
d[i] = -INF;
pre[i] = -;
in[i] = ;
}
queue<int>que;
que.push(x);
in[x] = ;
d[x] = ;
while(!que.empty())
{
u = que.front();
que.pop();
for(i = first[u]; i != -; i = edge[i].next)
{
v = edge[i].v;
if(in[v]) continue;
if(d[v] < d[u] + )
{
d[v] = d[u] + ;
pre[v] = u;
pre1[v] = i;
in[v] = ;
que.push(v);
}
}
}
int id,maxz = ;
for(i = ; i <= n; i ++)
{
if(maxz < d[i])
{
maxz = d[i];
id = i;
}
}
return id;
}
int main()
{
int cas,i,u,v,w,a,b,tmax,bb,aa,sn = ;
scanf("%d",&cas);
while(cas--)
{
scanf("%d",&n);
CL();
for(i = ; i < n; i ++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w,i);
add(v,u,w,i);
qu[i] = u;
qv[i] = v;
qw[i] = w;
}
b = spfa(a = spfa());
bb = b;
aa = a;
tmax = d[b];
while(b != a)
{
flag[b] = ;
pre2[pre[b]] = b;
b = pre[b];
}
flag[a] = ;
for(i = ; i <= n; i ++)
in[i] = ;
for(i = ; i <= n; i ++)
{
if(flag[i]||in[i])
{
dfs(i);
}
}
int minz = INF,num,res = -;
b = bb;
num = ;
while()
{
sp1[b] = dp[b]+tmax - num;
sp2[b] = num + dp[b];
num ++;
if(a == b) break;
b = pre[b];
}
int pos = ;
b = bb;
a = aa;
while(b != a)
{
sp2[pre[b]] = max(pos,sp2[pre[b]]);
pos = sp2[pre[b]];
b = pre[b];
}
b = bb;
a = aa;
pos = ;
while(a != b)
{
sp1[pre2[a]] = max(pos,sp1[pre2[a]]);
pos = sp1[pre2[a]];
a = pre2[a];
}
b = bb;
a = aa;
for(i = ; i < n; i ++)
{
if(flag[qu[i]]&&flag[qv[i]])
{
if(pre[qu[i]] == qv[i])
{
u = qu[i];
v = qv[i];
}
else
{
u = qv[i];
v = qu[i];
}
int tt = qw[i]*(max(sp1[v],sp2[u]));
if(minz > tt)
{
minz = tt;
res = i;
}
else if(minz == tt)
{
res = min(res,i);
}
}
else
{
if(minz > qw[i]*tmax)
{
minz = qw[i]*tmax;
res = i;
}
else if(minz == qw[i]*tmax)
{
res = min(res,i);
}
}
}
printf("Case #%d: %d\n",sn++,res);
}
return ;
}
HDU 4679 Terrorist’s destroy的更多相关文章
- 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 树的直径+dp
题意:给你一棵树,每条边都有值W,然后问你去掉一条边,令val = w*max(两颗新树的直径),求val最小值~ 做法,先求树的直径,然后算出直径上每个点的最长枝条长度.这样对于每一条边,假如是枝条 ...
- Terrorist’s destroy HDU - 4679
Terrorist’s destroy HDU - 4679 There is a city which is built like a tree.A terrorist wants to destr ...
- 树形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 ...
随机推荐
- 为win7添加ubuntu的启动引导项
利用MBRFix删除ubuntu的开机引导界面,恢复成win7引导之后,为win7添加ubuntu的启动引导项: 直接利用EasyBCD添加一个Grub2的引导项即可 参考:http://mathis ...
- JS的trim()方法
去除字符串左右两端的空格,在vbscript里面可以轻松地使用 trim.ltrim 或 rtrim,但在js中却没有这3个内置方法,需要手工编写.下面的实现方法是用到了正则表达式,效率不错,并把这三 ...
- 【云计算】Dockerfile、镜像、容器快速入门
Dockerfile.镜像.容器快速入门 1.1.Dockerfile书写示例 Dockerfile可以用来生成Docker镜像,它明确的定义了Image的生成过程.虽然直接修改容器也可以提交生成镜像 ...
- operator new3种情况详解
[本文链接] http://www.cnblogs.com/hellogiser/p/operator-new.html [代码] C++ Code 12345678910111213141516 ...
- 使用kettle转换中的JavaScript对密码进行加密和解密
日常开发中,为了确保账号和密码的安全,时常要对密码进行加密和解密.然而kettle是怎么对密码进行加密和解密的呢? 下面的代码需要再转换中的JavaScript中运行. var encrypted_p ...
- Java for LeetCode 140 Word Break II
Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each ...
- deep web
http://free.vpn.wwdhz.com/ (1小时vpn)http://thehiddenwiki.org (Hao123这样的导航网站)http://hss3uro2hsxfogf ...
- Android之Fragment(一)
Fragment的产生与介绍 Android运行在各种各样的设备中,有小屏幕的手机,超大屏的平板甚至电视.针对屏幕尺寸的差距,很多情况下,都是先针对手机开发一套App,然后拷贝一份,修改布局以适应平板 ...
- 各大OJ
北大POJ 杭电HDU 浙大ZOj 蓝桥杯 PAT
- SQL 外键
先新建2个表,写入数据 -- 创建测试主表. ID 是主键. CREATE TABLE test_main ( id INT, value ), PRIMARY KEY(id) ); -- 创建测试子 ...