HDU-4679-树的直径(树形dp)
2018-04-18 13:21
477 查看
Terrorist’s destroy
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1643 Accepted Submission(s): 558
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.
Sample Input 2 5 4 5 1 1 5 1 2 1 1 3 5 1 5 1 4 1 1 3 1 5 1 1 2 5 1
Sample Output Case #1: 2 Case #2: 3
Source 2013 Multi-University Training Contest 8 给出一颗树,每条边具有一个权值wi,定义一颗树的得分是这颗树上距离最远的两个点的距离,边的长度都是1.现在请选择一条边拆除,使得这条边上的权值与拆掉边后形成的两颗子树中最大的得分的乘积达到最小,输出这条边。 我们要知道每颗子树的直径,双dfs处理出 fm[u],sm[u],tm[u]记录以u为起点的前三大的路径和连接自那个连接点,然后枚举所有边,注意查找子树直径的时不可以通过这条边了。还是要注意前三大的直径必须来自于不同的临界点,否则可能出现非单链的情况。 第一次处理时没有计算出直径,,结果竟然能AC...,数据好弱啊,,后来改了改依然能AC.
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; #define inf 0x3f3f3f3f #pragma comment(linker, "/STACK:102400000,102400000") int first[100010],tot; int baba[100010]; int fm[100010],sm[100010],tm[100010]; int fid[100010],sid[100010],tid[100010]; struct Edge { int u,v,w,next; }e[201000]; void add(int u,int v,int w){ e[tot].u=u; e[tot].v=v; e[tot].w=w; e[tot].next=first[u]; first[u]=tot++; } void dfs1(int u,int fa) { fm[u]=sm[u]=tm[u]=0; fid[u]=sid[u]=tid[u]=0; baba[u]=fa; for(int i=first[u];i+1;i=e[i].next){ int v=e[i].v; if(v==fa) continue; dfs1(v,u); if(fm[v]+1>tm[u]&&v!=fid[u]&&v!=sid[u]){ tm[u]=fm[v]+1; tid[u]=v; if(tm[u]>sm[u]){ swap(tm[u],sm[u]); swap(tid[u],sid[u]); } if(sm[u]>fm[u]){ swap(sm[u],fm[u]); swap(sid[u],fid[u]); } } if(sm[v]+1>tm[u]&&v!=fid[u]&&v!=sid[u]){ tm[u]=sm[v]+1; tid[u]=v; if(tm[u]>sm[u]){ swap(tm[u],sm[u]); swap(tid[u],sid[u]); } if(sm[u]>fm[u]){ swap(sm[u],fm[u]); swap(sid[u],fid[u]); } } if(tm[v]+1>tm[u]&&v!=fid[u]&&v!=sid[u]){ tm[u]=tm[v]+1; tid[u]=v; if(tm[u]>sm[u]){ swap(tm[u],sm[u]); swap(tid[u],sid[u]); } if(sm[u]>fm[u]){ swap(sm[u],fm[u]); swap(sid[u],fid[u]); } } } } void dfs2(int u,int fa) { if(fid[fa]!=u&&fid[u]!=fa&&sid[u]!=fa&&fm[fa]+1>tm[u]){ tm[u]=fm[fa]+1; tid[u]=fa; if(tm[u]>sm[u]){ swap(tm[u],sm[u]); swap(tid[u],sid[u]); } if(sm[u]>fm[u]){ swap(sm[u],fm[u]); swap(sid[u],fid[u]); } } if(sid[fa]!=u&&fid[u]!=fa&&sid[u]!=fa&&sm[fa]+1>tm[u]){ tm[u]=sm[fa]+1; tid[u]=fa; if(tm[u]>sm[u]){ swap(tm[u],sm[u]); swap(tid[u],sid[u]); } if(sm[u]>fm[u]){ swap(sm[u],fm[u]); swap(sid[u],fid[u]); } } if(tid[fa]!=u&&fid[u]!=fa&&sid[u]!=fa&&tm[fa]+1>tm[u]){ tm[u]=tm[fa]+1; tid[u]=fa; if(tm[u]>sm[u]){ swap(tm[u],sm[u]); swap(tid[u],sid[u]); } if(sm[u]>fm[u]){ swap(sm[u],fm[u]); swap(sid[u],fid[u]); } } for(int i=first[u];~i;i=e[i].next){ int v=e[i].v; if(v==fa) continue; dfs2(v,u); } } int main() { int n,i,j,k,u,v,w; int t,cas=0; cin>>t; while(t--){ memset(first,-1,sizeof(first)); tot=0; scanf("%d",&n); for(i=1;i<n;++i){ scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } dfs1(1,0); dfs2(1,0); /*for(i=1;i<=n;++i) cout<<fm[i]<<' '<<sm[i]<<' '<<tm[i]<<endl;*/ int ans=inf,id=0; for(i=0;i<tot;i+=2){ u=e[i].u,v=e[i].v,w=e[i].w; int t1=0,t2=0; if(baba[v]==u){ t1=0,t2=0; if(fid[u]!=v&&sid[u]!=v){ t1=max(t1,fm[u]+sm[u]); } else if(sid[u]!=v&&tid[u]!=v){ t1=max(t1,sm[u]+tm[u]); } else t1=max(t1,fm[u]+tm[u]); if(fid[v]!=u&&sid[v]!=u){ t2=max(t2,fm[v]+sm[v]); } else if(sid[v]!=u&&tid[v]!=u){ t2=max(t2,sm[v]+tm[v]); } else t2=max(t2,fm[v]+tm[v]); } else{ if(fid[u]!=v&&sid[u]!=v){ t2=max(t2,fm[u]+sm[u]); } else if(sid[u]!=v&&tid[u]!=v){ t2=max(t2,sm[u]+tm[u]); } else t2=max(t2,fm[u]+tm[u]); if(fid[v]!=u&&sid[v]!=u){ t1=max(t1,fm[v]+sm[v]); } else if(sid[v]!=u&&tid[v]!=u){ t1=max(t1,sm[v]+tm[v]); } else t1=max(t1,fm[v]+tm[v]); } if(w*max(t1,t2)<ans){ ans=w*max(t1,t2); id=i; } } printf("Case #%d: %d\n",++cas,(id+2)/2); } return 0; }
相关文章推荐
- 【解题报告】HDU 4679 Terrorist’s destroy -- 树形dp 删一边求两子树直径
- hdu 4679 Terrorist’s destroy(树形DP)
- hdu 2196 Computer 树形DP或者树的直径
- 【HDU 5886】Tower Defence(树的直径+树形DP)
- hdu 4679 Terrorist’s destroy 树形dp水题 (2013多校联合)
- HDU 4679 Terrorist’s destroy (树形DP)
- HDU 5886 Tower Defence(树形dp|树的直径)
- hdu 4679 Terrorist’s destroy (树形dp)
- HDU 4679 Terrorist’s destroy (2013多校8 1004题 树形DP)
- HDU-4679 Terrorist’s destroy 树形DP,维护
- HDU 4679 Terrorist’s destroy(树形dp | 多校8)
- Hdu 2196 Computer (树的直径 或 树形DP)
- hdu 4679 Terrorist’s destroy 树的直径+dp
- HDU 3721 Building Roads 树形dp + 枚举直径
- hdu 4679 树形dp
- hdu 4679(树形dp)
- hdu 4679 Terrorist’s destroy(树形dp)
- hdu 4679 (树形DP)
- hdu 4679 Terrorist’s destroy 树形DP
- HDU 4679 Terrorist’s destroy (树形DP)