2013多校联合8 1004 Terrorist’s destroy(hdu 4679)
2013-08-15 21:04
447 查看
http://acm.hdu.edu.cn/showproblem.php?pid=4679
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 268 Accepted Submission(s): 74
Problem Description
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.
Input
The 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)
Output
For 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.
哎。。。又是赛后5分钟AC啊。。。伤不起。。。
思路,最后才想到解法,感觉有点麻烦,调试了半天。。。还是代码能力不足的结果。
我们队的方法是首先先设节点1为根节点,然后设len[i]表示以i节点为根的子树中的最长链,设dep[i]表示以i为根节点的子树中
距离i最远的节点到i的距离。设maxf[i]表示i的非子节点集中距离i的最远的点到i的距离。
这三个值可以用普通的树状DP解决,这里就不多说了。
接下来我们dfs从根节点遍历整棵树,当我们经过一个节点时,我们枚举它与它的子节点间的边,计算删除这条边所需的代价,
我们设当前经过的点为u,它的子节点为v,设边v--u的权值为val,删除边u--v后与v相连的那部分子树的最长链显然为len[v],现在关键是求与u相连的那部分子树的最长链,现在我们假设在dfs遍历到u时已经将u之上且不与u相连的最长链的长度求出,设为ma,这个可以由dfs从它的父节点传下来(具体看代码实现),那么现在的任务就是求与u相连或者u其他子节点(不包括v)的最长链的长度,再和ma比较。便可得到与u相连的子树中的最长链。首先u的其他子节点的最长链就是len[x](x是u的子节点且x不为v),然后求与u相连的最长链,我们可以求u的子节点中dep[x]+1最大的两个(不包括v),设为m1,m2,然后再加上maxf[u],这三个值里面去最大的两个相加即为所求。这样我们就得到了与u相连的子树中的最长链,同时我们可以将这个值传到节点v中,同节点u中的ma。这样我们就可以通过枚举,得到所要求的答案。
可能说的有些复杂,但是实现更加复杂。。。。除了上面所讲的外,还需要注意些细节,具体实现还是参考代码吧。
另外注意dfs会爆栈的,可以用#pragma comment(linker, "/STACK:1024000000,1024000000") 。
代码如下:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#define maxn 100010
#define ll long long
using namespace std;
int len[maxn],dep[maxn],maxf[maxn];
struct edge
{
int to;
int next;
int w,id;
}e[maxn<<1];
int box[maxn],cnt=0;
void init(int n)
{
memset(box,-1,sizeof(int)*n);
memset(len,0,sizeof(int)*n);
memset(dep,0,sizeof(int)*n);
memset(maxf,0,sizeof(int)*n);
cnt=0;
}
void add(int from,int to,int w,int id)
{
e[cnt].to=to;
e[cnt].w=w;
e[cnt].id=id;
e[cnt].next=box[from];
box[from]=cnt++;
}
ll Max;
int ansid;
void dfs1(int now,int fa)
{
int t,v;
int m1=0,m2=0;
for(t=box[now];t+1;t=e[t].next)
{
v=e[t].to;
if(v!=fa)
{
dfs1(v,now);
dep[now]=max(dep[now],dep[v]+1);
len[now]=max(len[now],len[v]);
if(dep[v]+1>=m1)
m2=m1,m1=dep[v]+1;
else if(dep[v]+1>=m2)
m2=dep[v]+1;
}
}
len[now]=max(len[now],m1+m2);
}
void dfs2(int now,int fa)
{
int t,v;
int m1=0,id1=0,m2=0,id2=0;
for(t=box[now];t+1;t=e[t].next)
{
v=e[t].to;
if(v!=fa)
{
if(dep[v]+1>=m1)
{
m2=m1;
id2=id1;
m1=dep[v]+1;
id1=v;
}
else if(dep[v]+1>=m2)
{
m2=dep[v]+1;
id2=v;
}
}
}
for(t=box[now];t+1;t=e[t].next)
{
v=e[t].to;
if(v!=fa)
{
if(id1==v)
{
maxf[v]=max(maxf[now],m2)+1;
dfs2(v,now);
}
else
{
maxf[v]=max(maxf[now],m1)+1;
dfs2(v,now);
}
}
}
}
void dfs3(int now,int fa,int ma)
{
int t,v;
int m1=0,m2=0,m3=0,id1=0,id2=0;
for(t=box[now];t+1;t=e[t].next)
{
v=e[t].to;
if(v!=fa)
{
if(dep[v]+1>=m1)
m3=m2,m2=m1,id2=id1,m1=dep[v]+1,id1=v;
else if(dep[v]+1>=m2)
m3=m2,m2=dep[v]+1,id2=v;
else if(dep[v]+1>=m3)
m3=v;
}
}
int n1=0,pid1=0,n2=0;
for(t=box[now];t+1;t=e[t].next)
{
v=e[t].to;
if(v!=fa)
{
if(len[v]>=n1)
n2=n1,n1=len[v],pid1=v;
else if(len[v]>=n2)
n2=len[v];
}
}
for(t=box[now];t+1;t=e[t].next)
{
v=e[t].to;
if(v!=fa)
{
int ans=ma;
if(v==id1)
ans=max(ans,max(m2+m3,m2+maxf[now]));
else if(v==id2)
ans=max(ans,max(m1+m3,m1+maxf[now]));
else
ans=max(ans,max(m1+m2,m1+maxf[now]));
if(v==pid1)
ans=max(ans,n2);
else
ans=max(ans,n1);
ll tmp=(ll)max(ans,len[v]);
if(tmp*e[t].w<Max)
{
Max=tmp*e[t].w;
ansid=e[t].id;
}
else if(tmp*e[t].w==Max&&ansid>e[t].id)
ansid=e[t].id;
dfs3(v,now,ans);
}
}
}
int main()
{
// freopen("dd.txt","r",stdin);
int ncase,T=0;
scanf("%d",&ncase);
while(ncase--)
{
int n,i,x,y,w;
scanf("%d",&n);
init(n+1);
for(i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&w);
add(x,y,w,i);
add(y,x,w,i);
}
ansid=0;
Max=(1LL<<62);
dfs1(1,0);
dfs2(1,0);
dfs3(1,0,0);
printf("Case #%d: %d\n",++T,ansid);
}
return 0;
}
Terrorist’s destroy
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 268 Accepted Submission(s): 74
Problem Description
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.
Input
The 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)
Output
For 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.
哎。。。又是赛后5分钟AC啊。。。伤不起。。。
思路,最后才想到解法,感觉有点麻烦,调试了半天。。。还是代码能力不足的结果。
我们队的方法是首先先设节点1为根节点,然后设len[i]表示以i节点为根的子树中的最长链,设dep[i]表示以i为根节点的子树中
距离i最远的节点到i的距离。设maxf[i]表示i的非子节点集中距离i的最远的点到i的距离。
这三个值可以用普通的树状DP解决,这里就不多说了。
接下来我们dfs从根节点遍历整棵树,当我们经过一个节点时,我们枚举它与它的子节点间的边,计算删除这条边所需的代价,
我们设当前经过的点为u,它的子节点为v,设边v--u的权值为val,删除边u--v后与v相连的那部分子树的最长链显然为len[v],现在关键是求与u相连的那部分子树的最长链,现在我们假设在dfs遍历到u时已经将u之上且不与u相连的最长链的长度求出,设为ma,这个可以由dfs从它的父节点传下来(具体看代码实现),那么现在的任务就是求与u相连或者u其他子节点(不包括v)的最长链的长度,再和ma比较。便可得到与u相连的子树中的最长链。首先u的其他子节点的最长链就是len[x](x是u的子节点且x不为v),然后求与u相连的最长链,我们可以求u的子节点中dep[x]+1最大的两个(不包括v),设为m1,m2,然后再加上maxf[u],这三个值里面去最大的两个相加即为所求。这样我们就得到了与u相连的子树中的最长链,同时我们可以将这个值传到节点v中,同节点u中的ma。这样我们就可以通过枚举,得到所要求的答案。
可能说的有些复杂,但是实现更加复杂。。。。除了上面所讲的外,还需要注意些细节,具体实现还是参考代码吧。
另外注意dfs会爆栈的,可以用#pragma comment(linker, "/STACK:1024000000,1024000000") 。
代码如下:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#define maxn 100010
#define ll long long
using namespace std;
int len[maxn],dep[maxn],maxf[maxn];
struct edge
{
int to;
int next;
int w,id;
}e[maxn<<1];
int box[maxn],cnt=0;
void init(int n)
{
memset(box,-1,sizeof(int)*n);
memset(len,0,sizeof(int)*n);
memset(dep,0,sizeof(int)*n);
memset(maxf,0,sizeof(int)*n);
cnt=0;
}
void add(int from,int to,int w,int id)
{
e[cnt].to=to;
e[cnt].w=w;
e[cnt].id=id;
e[cnt].next=box[from];
box[from]=cnt++;
}
ll Max;
int ansid;
void dfs1(int now,int fa)
{
int t,v;
int m1=0,m2=0;
for(t=box[now];t+1;t=e[t].next)
{
v=e[t].to;
if(v!=fa)
{
dfs1(v,now);
dep[now]=max(dep[now],dep[v]+1);
len[now]=max(len[now],len[v]);
if(dep[v]+1>=m1)
m2=m1,m1=dep[v]+1;
else if(dep[v]+1>=m2)
m2=dep[v]+1;
}
}
len[now]=max(len[now],m1+m2);
}
void dfs2(int now,int fa)
{
int t,v;
int m1=0,id1=0,m2=0,id2=0;
for(t=box[now];t+1;t=e[t].next)
{
v=e[t].to;
if(v!=fa)
{
if(dep[v]+1>=m1)
{
m2=m1;
id2=id1;
m1=dep[v]+1;
id1=v;
}
else if(dep[v]+1>=m2)
{
m2=dep[v]+1;
id2=v;
}
}
}
for(t=box[now];t+1;t=e[t].next)
{
v=e[t].to;
if(v!=fa)
{
if(id1==v)
{
maxf[v]=max(maxf[now],m2)+1;
dfs2(v,now);
}
else
{
maxf[v]=max(maxf[now],m1)+1;
dfs2(v,now);
}
}
}
}
void dfs3(int now,int fa,int ma)
{
int t,v;
int m1=0,m2=0,m3=0,id1=0,id2=0;
for(t=box[now];t+1;t=e[t].next)
{
v=e[t].to;
if(v!=fa)
{
if(dep[v]+1>=m1)
m3=m2,m2=m1,id2=id1,m1=dep[v]+1,id1=v;
else if(dep[v]+1>=m2)
m3=m2,m2=dep[v]+1,id2=v;
else if(dep[v]+1>=m3)
m3=v;
}
}
int n1=0,pid1=0,n2=0;
for(t=box[now];t+1;t=e[t].next)
{
v=e[t].to;
if(v!=fa)
{
if(len[v]>=n1)
n2=n1,n1=len[v],pid1=v;
else if(len[v]>=n2)
n2=len[v];
}
}
for(t=box[now];t+1;t=e[t].next)
{
v=e[t].to;
if(v!=fa)
{
int ans=ma;
if(v==id1)
ans=max(ans,max(m2+m3,m2+maxf[now]));
else if(v==id2)
ans=max(ans,max(m1+m3,m1+maxf[now]));
else
ans=max(ans,max(m1+m2,m1+maxf[now]));
if(v==pid1)
ans=max(ans,n2);
else
ans=max(ans,n1);
ll tmp=(ll)max(ans,len[v]);
if(tmp*e[t].w<Max)
{
Max=tmp*e[t].w;
ansid=e[t].id;
}
else if(tmp*e[t].w==Max&&ansid>e[t].id)
ansid=e[t].id;
dfs3(v,now,ans);
}
}
}
int main()
{
// freopen("dd.txt","r",stdin);
int ncase,T=0;
scanf("%d",&ncase);
while(ncase--)
{
int n,i,x,y,w;
scanf("%d",&n);
init(n+1);
for(i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&w);
add(x,y,w,i);
add(y,x,w,i);
}
ansid=0;
Max=(1LL<<62);
dfs1(1,0);
dfs2(1,0);
dfs3(1,0,0);
printf("Case #%d: %d\n",++T,ansid);
}
return 0;
}
相关文章推荐
- hdu 4679 Terrorist’s destroy 树形dp水题 (2013多校联合)
- HDU 4679 Terrorist’s destroy (2013多校8 1004题 树形DP)
- HDU 4669 Mutiples on a circle (2013多校联合7 1004)
- hdu 4679 Terrorist’s destroy 多校第八场
- HDU 4679 Terrorist’s destroy(树形dp | 多校8)
- HDU 4669 Mutiples on a circle (2013多校7 1004题)
- 2013多校联合3 1010 No Pain No Game(hdu 4630)
- 2013多校联合4 1001 Palindrome subsequence(hdu 4632)
- HDU 4637 Rain on your Fat brother 线段与半圆和线段交 简单题 (2013多校联合)
- hdu 4677 并查集+分块算法 好题 (2013多校联合)
- HDU 4864 Task (2014多校联合训练第一场1004) 解题报告(贪心)
- 2013 多校联合 C Partition (hdu 4602)
- 2013多校联合2 I Warm up 2(hdu 4619)
- hdu 4617 2013多校联合训练第二场weapon简单的计算几何
- 2013多校联合 3 B Reincarnation (hdu 4622)
- hdu 4361 2013多校联合训练第3场最后一题
- HDU 4691 Front compression (2013 多校联合9 1006)
- HDU 4679 Terrorist’s destroy 解题报告
- HDU 4679 Terrorist’s destroy (树形DP)
- HDU 4632 2013多校联合第4场 A - Palindrome subsequence