/* HDU 4679 Terrorist’s destroy 给一棵树,任意删一条边,树分成了两个部分(a,b),求min( max(a.直径,b.直径) * v.w ) 最大直径乘以边权 积的最小值 解法: 先找出整棵树的直径所在,即两个端点ds de 然后保存每个点到ds和de之间的距离 dds[] dde[] 然后从ds(de)开始搜 每个点保存子树中到de(ds)之间距离的最大值mde[](mds[]),这里要用到dds[]和dde[] 然后枚举删边,从ds(或de)开始搜 当删father,child之间的一条边的时候,分成了两个子树,我们的max(mde[father],mds[child])就是两个子树的最大直径 然后就没有然后了。。。。 几乎每一部操作都要搜两次 */ #pragma comment(linker, "/STACK:102400000,102400000") #include <functional> #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <string> #include <vector> #include <ctime> #include <queue> #include <cmath> #include <set> #define CLR(a,v) memset(a,v,sizeof(a)) using namespace std; typedef long long ll; typedef pair<int,int> pii; const int INF = 1<<29; const int N = 1e5+10; struct node{ int hid , w , pid; // houseid wight pathid node(){} node(int a,int b,int v):hid(a),w(b),pid(v){} }; vector <node > m[N]; int ds,de; // 直径的端点 int dds[N],dde[N]; // 以ds、de为根深度 int mds[N],mde[N]; // 以ds(de)为根每个节点存其子树节点到de(ds)的最远距离 void dfs(int now,int fa,int& dtmp,int ddtmp[]){ // 求端点 if(m[now].size()==1 && m[now][0].hid==fa && ddtmp[now] > ddtmp[dtmp]){ // 如果是叶子 dtmp = now;return; } int child; for(int i = 0 ; i < m[now].size() ; i++){ if( (child=m[now][i].hid) == fa)continue; ddtmp[child] = ddtmp[now] + 1; dfs(child,now,dtmp,ddtmp); } } void dfs(int now,int fa,int mdtmp[],int ddtmp[]){ // 求最远距离 int child ; mdtmp[now] = ddtmp[now]; for(int i = 0 ; i < m[now].size() ; i++){ if( (child=m[now][i].hid) == fa)continue; dfs(child ,now , mdtmp,ddtmp); mdtmp[now] = max(mdtmp[now],mdtmp[child]); } } int ans , ansid; void dfs(int now,int fa){ // 枚举删边,删完一条边后分成了两段 int child; for(int i = 0; i < m[now].size() ; i++){ if( (child=m[now][i].hid) == fa )continue; //判断是不是直径(判断两段的最长链相加等于直径长)dds[de]就是直径长 //int w = m[now][i].w * ( (dds[now] + dde[child] +1 == dds[de]) ? (max(mds[now] , mde[child])) : (dds[de]) ); int w = m[now][i].w * max(mds[now] , mde[child]); if(w < ans){ ans = w; ansid = m[now][i].pid; }else if(w == ans && m[now][i].pid < ansid) ansid = m[now][i].pid; dfs(child,now); } } int main(){ //freopen("in","r",stdin); //freopen("out.txt","w",stdout); // g++ 扩栈 //int size = 20 << 20; // 20MB //char *p = (char*)malloc(size) + size; //__asm__("movl %0, %%esp\n" :: "r"(p)); int T,n,trash=0,ca=1;cin >> T; while(T--){ scanf("%d",&n); for(int i = 1 ; i < n ; i++){ int a,b,v; scanf("%d%d%d" , &a , &b , &v); node c1(b,v,i),c2(a,v,i); m[a].push_back(c1); m[b].push_back(c2); } ds = de = 0; CLR(dds,0);dds[1]=1; dfs(1 , 0 , ds , dds); // only find ds CLR(dde,0);CLR(dds,0);dde[ds]=1; dfs(ds , 0 , de , dds); // find de and calc dds[] dfs(de , 0 , trash , dde); // only calc dde[] CLR(mds,0);mds[de]=0; dfs(de,0,mds,dds); CLR(mde,0);mde[ds]=0; dfs(ds,0,mde,dde); ans = ansid = INF; dfs(ds,0); printf("Case #%d: %d\n",ca++,ansid); for(int i = 0 ; i <= n ; i++) m[i].clear(); } return 0; }