uva11354 LCA+最小生成树+dp
源自大白书
题意 有n座城市通过m条双向道路相连,每条道路都有一个危险系数。你的任务是回答若干个询问,每个询问包含一个起点s和一个终点t,要求找到一条从s到t的路,使得途径所有的边的大最大危险系数最小。
解: 首先求出最小生成树,并把它改写成有根树,让fa[i]和cost[i]分别表示节点i的父亲编号和它与父亲之间的边权,L[i]表示节点i的深度,接下来通过预处理计算出数组anc 和 maxcost 其中anc[i][j] 表示节点i的2^j 级祖先的编号 macost[i][j] 表示i到2^j级 祖先之间的最大权值。
有了预处理 私用LCA 来查询结果, 查询p,q, 并且p比q深, 则可以先把p提升到和q处于同一级的位置,然后用二进制展开的方法不断把p和q同时往上提(保证二者深度相等),同时更新最大的边权
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <string.h> 5 #include <vector> 6 using namespace std; 7 const int maxn = 50000+10; 8 const int INF =2000000000; 9 struct Edge{ 10 int from,to, dist; 11 bool operator <(const Edge & rhs)const{ 12 return dist<rhs.dist; 13 } 14 }E[maxn*2]; 15 struct ed{ 16 int to,dist; 17 }; 18 vector<ed> G[maxn]; 19 int fa[maxn],per[maxn],cost[maxn],L[maxn]; 20 int anc[maxn][20],maxcost[maxn][20]; 21 void inti(int n){ 22 for(int i =0; i<n; i++){ 23 per[i] = i; 24 G[i].clear(); 25 } 26 } 27 void preprocess( int n){ 28 for(int i=0; i<n ; i++){ 29 anc[i][0] = fa[i]; maxcost[i][0]=cost[i]; 30 for(int j=1; (1<<j)<n; j++) anc[i][j]=-1; 31 } 32 for(int j =1; (1<<j)<n; j++) 33 for(int i=0; i<n; i++){ 34 if(anc[i][j-1]!=-1){ 35 int a = anc[i][j-1]; 36 anc[i][j]=anc[a][j-1]; 37 maxcost[i][j] = max(maxcost[i][j-1],maxcost[a][j-1]); 38 } 39 } 40 } 41 int fid(int u){ 42 return per[u]==u?u:(per[u]= fid(per[u])); 43 } 44 void dfs(int u, int p,int dist, int depth){ 45 fa[u]=p; cost[u] = dist; L[u] = depth; 46 for(int i = 0; i<(int)G[u].size(); ++i){ 47 ed e = G[u][i]; 48 if(e.to == p) continue; 49 dfs(e.to,u,e.dist,depth+1); 50 } 51 } 52 int query(int p, int q){ 53 int log; 54 if(L[p]<L[q]) swap(p,q); 55 for( log =1; (1<<log)<=L[p]; log++); log--; 56 int ans=-INF; 57 for(int i = log ; i>=0; i--) 58 if( L[p] - (1<<i) >= L[q] ){ 59 ans = max(ans,maxcost[p][i]); 60 p = anc[p][i]; 61 } 62 if(p==q) return ans; 63 for(int i=log; i>=0; i--) 64 if(anc[p][i]!=-1 && anc[p][i]!=anc[q][i]){ 65 ans = max(ans,maxcost[p][i]); p = anc[p][i]; 66 ans = max(ans,maxcost[q][i]); q = anc[q][i]; 67 } 68 ans = max(ans,cost[p]); 69 ans = max(ans,cost[q]); 70 return ans; 71 } 72 int main() 73 { 74 int n,m,f=0; 75 while(scanf("%d%d",&n,&m)==2){ 76 inti(n); 77 for(int i=0; i<m ; i++){ 78 int x,y,d; 79 scanf("%d%d%d",&x,&y,&d); 80 x--,y--; 81 E[i]=(Edge){x,y,d}; 82 } 83 int lest = n; 84 sort(E,E+m); 85 for(int i=0; i<m; i++){ 86 int a = E[i].from,b=E[i].to, dist= E[i].dist; 87 int ca = fid(a),cb = fid(b); 88 if(ca!=cb){ 89 per[ca] =cb; 90 lest--; 91 G[a].push_back((ed){b,dist} ); 92 G[b].push_back((ed){a,dist} ); 93 if(lest==1) break; 94 } 95 } 96 dfs(0,-1,0,0); 97 preprocess(n); 98 int Q; 99 if(f) 100 puts(""); 101 else f=1; 102 scanf("%d",&Q); 103 for(int i =0; i<Q; i++){ 104 int s,t; 105 scanf("%d%d",&s,&t); 106 s--;t--; 107 printf("%d\n",query(s,t)); 108 } 109 110 } 111 112 return 0; 113 }