hdu4679
题目
就是给你一棵树,每条边有边权值,去掉这条边花费他的边权代价,然后树会分成两个子树,求两个个子树的最长链的最大值和去掉边的代价的乘积的最小值,输出那条边。
思路
做了一些树型dp,还是感觉学习了是什么鬼。。。
http://blog.csdn.net/yang_7_46/article/details/9988655 这位博主讲得很好了。
首先是学习了找树的最长链,两遍dfs,然后预处理每个点及其子树到两端点的最长距离,然后分情况考虑删去的边在不在树的最长链上。
代码
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<stack>
using namespace std;
typedef long long ll;
const int maxn=100100;
int head[maxn],tot,n,id,len,ans;
int ds[maxn],dt[maxn];
int mt[maxn],ms[maxn];
struct node
{
int next;
int to;
int w;
int id;
} edge[maxn*2];
void addedge(int from,int to,int w,int id)
{
edge[tot].to=to;
edge[tot].next=head[from];
edge[tot].w=w;
edge[tot].id=id;
head[from]=tot++;
}
void dfs1(int u,int fa)
{
for(int i=head[u]; ~i; i=edge[i].next)
{
int v=edge[i].to;
if(fa==v) continue;
ds[v]=ds[u]+1;
dfs1(v,u);
}
}
void dfs2(int u,int fa)
{
for(int i=head[u]; ~i; i=edge[i].next)
{
int v=edge[i].to;
if(fa==v) continue;
dt[v]=dt[u]+1;
dfs2(v,u);
}
}
void d1(int u,int fa)
{
ms[u]=ds[u];
for(int i=head[u]; ~i; i=edge[i].next)
{
int v=edge[i].to;
if(v==fa) continue;
d1(v,u);
ms[u]=max(ms[u],ms[v]);
}
}
void d2(int u,int fa)
{
mt[u]=dt[u];
for(int i=head[u]; ~i; i=edge[i].next)
{
int v=edge[i].to;
if(v==fa) continue;
d2(v,u);
mt[u]=max(mt[u],mt[v]);
}
}
void solve(int u,int fa)
{
int w;
for(int i=head[u]; ~i; i=edge[i].next)
{
int v=edge[i].to;
if(v==fa) continue;
if(ds[u]+1+dt[v]==len)
w=edge[i].w*max(ms[u],mt[v]);
else w=edge[i].w*len;
if(w<ans)
{
ans=w;
id=edge[i].id;
}
else if(w==ans&&edge[i].id<id)
id=edge[i].id;
solve(v,u);
}
}
int main()
{
int kase=1;
int T;
scanf("%d",&T);
while(T--)
{
ans=0x3f3f3f3f;
tot=0;
memset(head,-1,sizeof(head));
scanf("%d",&n);
for(int i=1; i<=n-1; i++)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
addedge(a,b,c,i);
addedge(b,a,c,i);
}
ds[1]=ds[0]=0;
dfs1(1,0);
int s=0;
for(int i=1; i<=n; i++) if(ds[i]>ds[s]) s=i;
ds[s]=0;
dfs1(s,0);
int t=0;
for(int i=1; i<=n; i++) if(ds[i]>ds[t]) t=i;
len=ds[t];
dt[t]=0;
dfs2(t,0);
d1(t,0);
d2(s,0);
solve(s,0);
printf("Case #%d: %d\n", kase++, id);
}
return 0;
}