首先,对于所有从x能到达y的路径中,限重越大越好
因此我们用Kruskal最大生成树得到一片森林(不一定都联通)
之后dfs维护森林的深度和LCA的预处理limit[x][0](x向上跳2^i步的边权最小值)
对于每个询问,求x和y到lca的边权最小值即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define N 10010 6 #define M 100010 7 #define INF 100000000 8 struct fx{ 9 int to,w,from,next; 10 11 }e[M],t[M]; 12 int size,n,m,q,head[M],maxl[N],father[N]; 13 int fa[N][25],limit[N][25],deep[N],vis[N]; 14 void uni(int x,int y,int z){ 15 size++; 16 e[size].to=y; 17 e[size].from=x; 18 e[size].w=z; 19 } 20 void Uni(int x,int y,int z){ 21 size++; 22 t[size].next=head[x]; 23 head[x]=size; 24 t[size].to=y; 25 t[size].from=x; 26 t[size].w=z; 27 } 28 bool cmp(fx a,fx b){ 29 return a.w>b.w; 30 } 31 int find(int x){ 32 if (father[x]!=x) father[x]=find(father[x]); 33 return father[x]; 34 } 35 void swap(int &x,int &y){ 36 int tmp; 37 tmp=x; 38 x=y; 39 y=tmp; 40 } 41 void kruskal(){ 42 int x,y,r1,r2,cnt; 43 for (int i=1;i<=n;i++) 44 father[i]=i; 45 sort(e+1,e+m+1,cmp); 46 size=0;cnt=n; 47 for (int p=1;p<=m&&cnt>1;p++){ 48 x=e[p].from; 49 y=e[p].to; 50 r1=find(x); 51 r2=find(y); 52 if (r1!=r2){ 53 father[r1]=r2; 54 cnt--; 55 Uni(x,y,e[p].w); 56 Uni(y,x,e[p].w); 57 } 58 } 59 } 60 void dfs(int x,int xx){ 61 vis[x]=1; 62 fa[x][0]=xx; 63 for (int k=head[x];k;k=t[k].next){ 64 int y=t[k].to; 65 if (y==xx) continue; 66 deep[y]=deep[x]+1; 67 limit[y][0]=t[k].w; 68 dfs(y,x); 69 } 70 } 71 void Limit(){ 72 for (int j=1;j<=20;j++) 73 for (int i=1;i<=n;i++){ 74 limit[i][j]=min(limit[fa[i][j-1]][j-1],limit[i][j-1]); 75 fa[i][j]=fa[fa[i][j-1]][j-1]; 76 } 77 } 78 int LCA(int x,int y){ 79 int d,minl=INF; 80 if (deep[x]<deep[y]) 81 swap(x,y); 82 d=deep[x]-deep[y]; 83 for (int i=0;i<=20;i++) 84 if ((1<<i)&d) { 85 minl=min(minl,min(limit[x][i],limit[x][0])); 86 x=fa[x][i]; 87 } 88 if (x==y) return minl;//相等则不需向上跳 89 for (int i=20;i>=0;i--) 90 if (fa[x][i]!=fa[y][i]){ 91 minl=min(minl,min(limit[x][i],limit[y][i])); 92 x=fa[x][i]; 93 y=fa[y][i]; 94 } 95 minl=min(minl,min(limit[x][0],limit[y][0])); 96 return minl; 97 } 98 int main(){ 99 int x,y,z,r1,r2; 100 size=0; 101 scanf("%d %d",&n,&m); 102 for (int i=1;i<=m;i++){ 103 scanf("%d %d %d",&x,&y,&z); 104 uni(x,y,z); 105 } 106 kruskal(); 107 for (int i=1;i<=n;i++) 108 if (!vis[i]){ 109 deep[i]=1; 110 dfs(i,0);//森林 111 } 112 Limit(); 113 scanf("%d",&q); 114 for (int i=1;i<=q;i++){ 115 scanf("%d %d",&x,&y); 116 r1=find(x); 117 r2=find(y); 118 if (r1!=r2) printf("-1\n"); 119 else printf("%d\n",LCA(x,y)); 120 } 121 return 0; 122 }