题意:
有一棵树,要删掉一条边,删边后形成两棵树,要求两棵树的最长直径的最大值乘以删掉的边权的值最小。
题解:
两次DFS:
第一次计算出从当前点到叶子的最长三条无公共边的链。
第二次,如果要删掉某条边,就可以知道两棵树的最长直径了:一条是当前子树的最长链,一条是祖先的不包含当前子树的最长链。
又忘了开栈开关……
据说这题的数据特别水,把边权全当1,输出最长链的短链也能过。
//Time:921ms
//Memory:14312KB
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define MAXN 100010
#define INF 1000000007
#define FI first
#define SE second
#define MP(x,y) make_pair(x,y)
pair<int,int> tree[MAXN][3];
int he[MAXN],to[MAXN*2],nex[MAXN*2],co[MAXN*2],id[MAXN*2],top;
int ans;
long long best;
void add(int u,int v,int w,int i)
{
to[top]=v;
nex[top]=he[u];
co[top]=w;
id[top]=i;
he[u]=top++;
}
void upd(int h,int len,int whi)
{
if(len>tree[h][0].FI)
tree[h][2]=tree[h][1],tree[h][1]=tree[h][0],tree[h][0]=MP(len,whi);
else if(len>tree[h][1].FI)
tree[h][2]=tree[h][1],tree[h][1]=MP(len,whi);
else if(len>tree[h][2].FI)
tree[h][2]=MP(len,whi);
}
int dfs1(int h,int fa)
{
for(int i=he[h];i!=-1;i=nex[i])
if(fa!=to[i])
upd(h,dfs1(to[i],h),to[i]);
return tree[h][0].FI+1;
}
pair<int,int> mget(int h,int whi)
{
pair<int,int> ret;
if(whi==tree[h][0].SE)
ret=MP(tree[h][1].FI+tree[h][2].FI,tree[h][1].FI);
else if(whi==tree[h][1].SE)
ret=MP(tree[h][0].FI+tree[h][2].FI,tree[h][0].FI);
else ret=MP(tree[h][1].FI+tree[h][0].FI,tree[h][0].FI);
return ret;
}
void dfs2(int h,int fa,int pre1,int pre2,int whi)
{
long long tmp=max(max(pre2,pre1),mget(h,0).FI)*(long long)co[whi];
if(h!=1&&(tmp<best||(tmp==best&&ans>id[whi])))
{
best=tmp;
ans=id[whi];
}
pair<int,int> tpa;
for(int i=he[h];i!=-1;i=nex[i])
if(to[i]!=fa)
{
tpa=mget(h,to[i]);
dfs2(to[i],h,max(pre1+1,tpa.SE),max(max(pre2,pre1+1+tpa.SE),tpa.FI),i);
}
}
int main()
{
//freopen("/home/moor/Code/input","r",stdin);
int ncase,n;
scanf("%d",&ncase);
for(int h=1;h<=ncase;++h)
{
scanf("%d",&n);
memset(he,-1,sizeof(he));
memset(tree,0,sizeof(tree));
top=0;
for(int i=1;i<n;++i)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w,i);
add(v,u,w,i);
}
ans=INF;
best=100000000000000LL;
dfs1(1,-1);
dfs2(1,-1,-1,0,-1);
printf("Case #%d: %d\n",h,ans);
}
return 0;
}