Description
给你N个点的无向图 (1 <= N <= 15,000),记为:1…N。
图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000).
现在有 K个询问 (1 < = K < = 15,000)。
每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
Input
第一行: N, M, K。
第2..M+1行: 三个正整数:X, Y, and D (1 <= X <=N; 1 <= Y <= N). 表示X与Y之间有一条长度为D的边。
第M+2..M+K+1行: 每行两个整数A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
Output
对每个询问,输出最长的边最小值是多少。
求出最小生成树并用树链剖分维护
查询时查找最小生成树上A,B两点间路径上的最大值
时间复杂度O(Klog2N)
#include<cstdio> #include<vector> #include<algorithm> int n,m,k,p1,p2,p3; struct edge{ int from,to,w; edge(){} edge(int a,int b,int c){ from=a;to=b;w=c; } }; struct edge1{ int to,w; edge1(int b,int c){ to=b;w=c; } }; bool operator<(edge a,edge b){ return a.w<b.w; } int ms[15003]; int pa[15005],top[15005],sz[15005],dep[15005],son[15005],el[15005],id[15005],idp=1; inline int getp(int a){ while(a^ms[a])a=ms[a]; return a; } inline bool merge(int a,int b){ int c=getp(a),d=getp(b); if(c==d)return false; ms[c]=d; while(ms[a]^d)c=ms[a],ms[a]=d,a=c; while(ms[b]^d)c=ms[b],ms[b]=d,b=c; return true; } int tr[32769]; edge es[60001]; std::vector<edge1> vs[15005]; int ep=0; int dfs1(int w,int pa1,int dp){ pa[w]=pa1; sz[w]=1; dep[w]=dp; for(int i=vs[w].size()-1,u;i>=0;i--){ if((u=vs[w][i].to)==pa1)continue; sz[w]+=dfs1(u,w,dp+1); if(!son[w])son[w]=u; else if(sz[u]>sz[son[w]])son[w]=u; } } int dfs2(int w,int tp,int wv){ id[w]=idp++; el[id[w]]=wv; top[w]=tp; for(int i=vs[w].size()-1,u;i>=0;i--){ if((u=vs[w][i].to)==pa[w])continue; if(u==son[w])dfs2(u,tp,vs[w][i].w); } for(int i=vs[w].size()-1,u;i>=0;i--){ if((u=vs[w][i].to)==pa[w])continue; if(u==son[w])continue; dfs2(u,u,vs[w][i].w); } } inline int max(int a,int b){return a>b?a:b;} inline void setv(int w,int v){ w+=16384; tr[w]=v; for(w>>=1;w;w>>=1)tr[w]=max(tr[w+w],tr[w+w+1]); } void build(){ for(int i=1;i<idp;i++)tr[i+16384]=el[i]; for(int i=16383;i>0;i--)tr[i]=max(tr[i+i],tr[i+i+1]); } inline int getmax(int a,int b){ int ans=0; for(a+=16383,b+=16385;a^b^1;a>>=1,b>>=1){ if(~a&1)ans=max(ans,tr[a^1]); if(b&1)ans=max(ans,tr[b^1]); } return ans; } int ask(int x,int y){ int a=top[x],b=top[y],c; int ans=0; while(a!=b){ if(dep[a]<dep[b])c=a,a=b,b=c,c=x,x=y,y=c; ans=max(ans,getmax(id[a],id[x])); x=pa[a]; a=top[x]; } if(id[x]<id[y])setv(id[x],0),ans=max(ans,getmax(id[x],id[y])),setv(id[x],el[id[x]]); else setv(id[y],0),ans=max(ans,getmax(id[y],id[x])),setv(id[y],el[id[y]]); return ans; } int main(){ scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++)ms[i]=i; for(int i=0;i<m;i++){ scanf("%d%d%d",&p1,&p2,&p3); es[ep++]=edge(p1,p2,p3); } std::sort(es,es+ep); for(int i=0,a,b;i<ep;i++){ if(merge(a=es[i].from,b=es[i].to)){ vs[a].push_back(edge1(b,es[i].w)); vs[b].push_back(edge1(a,es[i].w)); } } dfs1(1,0,0); dfs2(1,0,0); build(); for(int i=0;i<k;i++){ scanf("%d%d",&p1,&p2); printf("%d\n",ask(p1,p2)); } return 0; }