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
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.
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)
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
给出一颗树,每条边具有一个权值wi,定义一颗树的得分是这颗树上距离最远的两个点的距离,边的长度都是1.现在请选择一条边拆除,使得这条边上的权值与拆掉边后形成的两颗子树中最大的得分的乘积达到最小,输出这条边。
我们要知道每颗子树的直径,双dfs处理出 fm[u],sm[u],tm[u]记录以u为起点的前三大的路径和连接自那个连接点,然后枚举所有边,注意查找子树直径的时不可以通过这条边了。还是要注意前三大的直径必须来自于不同的临界点,否则可能出现非单链的情况。
第一次处理时没有计算出直径,,结果竟然能AC...,数据好弱啊,,后来改了改依然能AC.
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 #define inf 0x3f3f3f3f 7 #pragma comment(linker, "/STACK:102400000,102400000") 8 int first[100010],tot; 9 int baba[100010]; 10 int fm[100010],sm[100010],tm[100010]; 11 int fid[100010],sid[100010],tid[100010]; 12 struct Edge 13 { 14 int u,v,w,next; 15 }e[201000]; 16 void add(int u,int v,int w){ 17 e[tot].u=u; 18 e[tot].v=v; 19 e[tot].w=w; 20 e[tot].next=first[u]; 21 first[u]=tot++; 22 } 23 void dfs1(int u,int fa) 24 { 25 fm[u]=sm[u]=tm[u]=0; 26 fid[u]=sid[u]=tid[u]=0; 27 baba[u]=fa; 28 for(int i=first[u];i+1;i=e[i].next){ 29 int v=e[i].v; 30 if(v==fa) continue; 31 dfs1(v,u); 32 if(fm[v]+1>tm[u]&&v!=fid[u]&&v!=sid[u]){ 33 tm[u]=fm[v]+1; 34 tid[u]=v; 35 if(tm[u]>sm[u]){ 36 swap(tm[u],sm[u]); 37 swap(tid[u],sid[u]); 38 } 39 if(sm[u]>fm[u]){ 40 swap(sm[u],fm[u]); 41 swap(sid[u],fid[u]); 42 } 43 } 44 if(sm[v]+1>tm[u]&&v!=fid[u]&&v!=sid[u]){ 45 tm[u]=sm[v]+1; 46 tid[u]=v; 47 if(tm[u]>sm[u]){ 48 swap(tm[u],sm[u]); 49 swap(tid[u],sid[u]); 50 } 51 if(sm[u]>fm[u]){ 52 swap(sm[u],fm[u]); 53 swap(sid[u],fid[u]); 54 } 55 } 56 if(tm[v]+1>tm[u]&&v!=fid[u]&&v!=sid[u]){ 57 tm[u]=tm[v]+1; 58 tid[u]=v; 59 if(tm[u]>sm[u]){ 60 swap(tm[u],sm[u]); 61 swap(tid[u],sid[u]); 62 } 63 if(sm[u]>fm[u]){ 64 swap(sm[u],fm[u]); 65 swap(sid[u],fid[u]); 66 } 67 } 68 } 69 } 70 void dfs2(int u,int fa) 71 { 72 if(fid[fa]!=u&&fid[u]!=fa&&sid[u]!=fa&&fm[fa]+1>tm[u]){ 73 tm[u]=fm[fa]+1; 74 tid[u]=fa; 75 if(tm[u]>sm[u]){ 76 swap(tm[u],sm[u]); 77 swap(tid[u],sid[u]); 78 } 79 if(sm[u]>fm[u]){ 80 swap(sm[u],fm[u]); 81 swap(sid[u],fid[u]); 82 } 83 } 84 if(sid[fa]!=u&&fid[u]!=fa&&sid[u]!=fa&&sm[fa]+1>tm[u]){ 85 tm[u]=sm[fa]+1; 86 tid[u]=fa; 87 if(tm[u]>sm[u]){ 88 swap(tm[u],sm[u]); 89 swap(tid[u],sid[u]); 90 } 91 if(sm[u]>fm[u]){ 92 swap(sm[u],fm[u]); 93 swap(sid[u],fid[u]); 94 } 95 } 96 if(tid[fa]!=u&&fid[u]!=fa&&sid[u]!=fa&&tm[fa]+1>tm[u]){ 97 tm[u]=tm[fa]+1; 98 tid[u]=fa; 99 if(tm[u]>sm[u]){ 100 swap(tm[u],sm[u]); 101 swap(tid[u],sid[u]); 102 } 103 if(sm[u]>fm[u]){ 104 swap(sm[u],fm[u]); 105 swap(sid[u],fid[u]); 106 } 107 } 108 for(int i=first[u];~i;i=e[i].next){ 109 int v=e[i].v; 110 if(v==fa) continue; 111 dfs2(v,u); 112 } 113 } 114 int main() 115 { 116 int n,i,j,k,u,v,w; 117 int t,cas=0; 118 cin>>t; 119 while(t--){ 120 memset(first,-1,sizeof(first)); 121 tot=0; 122 scanf("%d",&n); 123 for(i=1;i<n;++i){ 124 scanf("%d%d%d",&u,&v,&w); 125 add(u,v,w); 126 add(v,u,w); 127 } 128 dfs1(1,0); 129 dfs2(1,0); 130 /*for(i=1;i<=n;++i) 131 cout<<fm[i]<<' '<<sm[i]<<' '<<tm[i]<<endl;*/ 132 int ans=inf,id=0; 133 for(i=0;i<tot;i+=2){ 134 u=e[i].u,v=e[i].v,w=e[i].w; 135 int t1=0,t2=0; 136 if(baba[v]==u){ 137 t1=0,t2=0; 138 if(fid[u]!=v&&sid[u]!=v){ 139 t1=max(t1,fm[u]+sm[u]); 140 } 141 else if(sid[u]!=v&&tid[u]!=v){ 142 t1=max(t1,sm[u]+tm[u]); 143 } 144 else t1=max(t1,fm[u]+tm[u]); 145 146 if(fid[v]!=u&&sid[v]!=u){ 147 t2=max(t2,fm[v]+sm[v]); 148 } 149 else if(sid[v]!=u&&tid[v]!=u){ 150 t2=max(t2,sm[v]+tm[v]); 151 } 152 else t2=max(t2,fm[v]+tm[v]); 153 154 155 } 156 else{ 157 if(fid[u]!=v&&sid[u]!=v){ 158 t2=max(t2,fm[u]+sm[u]); 159 } 160 else if(sid[u]!=v&&tid[u]!=v){ 161 t2=max(t2,sm[u]+tm[u]); 162 } 163 else t2=max(t2,fm[u]+tm[u]); 164 165 if(fid[v]!=u&&sid[v]!=u){ 166 t1=max(t1,fm[v]+sm[v]); 167 } 168 else if(sid[v]!=u&&tid[v]!=u){ 169 t1=max(t1,sm[v]+tm[v]); 170 } 171 else t1=max(t1,fm[v]+tm[v]); 172 } 173 if(w*max(t1,t2)<ans){ 174 ans=w*max(t1,t2); 175 id=i; 176 } 177 } 178 printf("Case #%d: %d ",++cas,(id+2)/2); 179 } 180 return 0; 181 }