最小生成樹和倍增法求lca(Uva11354Bond)
阿新 • • 發佈:2019-02-08
#include<bits/stdc++.h> #define maxn 600000 #define inf (1124984) using namespace std; int head[maxn],book[maxn],deep[maxn],pre[maxn],fa[maxn],mxcost[maxn][30],cost[maxn],p[maxn][30]; int n,m,k,cnt=0; struct Edge{int from,to,w;}e[maxn]; struct Edg{int to,next,w;}edge[maxn]; int find(int x){return x==pre[x]?x:pre[x]=find(pre[x]);}//並查集 bool cmp(Edge a,Edge b){return a.w<b.w;} void add(int u,int v,int w) { edge[++cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].w=w; } void MinTree()//最小生成樹,克魯斯卡爾名字不會打了,就。。 { for(int i=1;i<=n;i++) pre[i]=i; sort(e+1,e+m+1,cmp); int num=0; for(int i=1;i<=m;i++) { int fx=find(e[i].from),fy=find(e[i].to); if(fx!=fy) { pre[fx]=fy; num++; add(e[i].from,e[i].to,e[i].w); add(e[i].to,e[i].from,e[i].w); if(num==n-1) break; } } } void DFS(int x) { book[x]=1; for(int i=head[x];i;i=edge[i].next) { int j=edge[i].to; if(!book[j]) { fa[j]=x; deep[j]=deep[x]+1; cost[j]=edge[i].w; DFS(j); } } } void preprocess() { for(int i=1;i<=n;i++) { p[i][0]=fa[i];mxcost[i][0]=cost[i]; for(int j=1;(1<<j)<=n;j++) p[i][j]=-1;//沒有父親的節點初始化為-1 } for(int j=1;(1<<j)<=n;j++) for(int i=1;i<=n;i++) { int fat=p[i][j-1]; if(fat!=-1) { p[i][j]=p[fat][j-1]; mxcost[i][j]=max(mxcost[i][j-1],mxcost[fat][j-1]);//最大的邊權等於這個點到他的2^j-1和2^j-1到2^j的最大邊權 } } /* for(int j=1;(1<<j)<=n;j++) for(int i=1;i<=n;i++) cout<<mxcost[i][j]<<"~"<<i<<j<<"\n";*/ } int query(int a,int b)//套用lca的模板 { if(deep[a]<deep[b]) swap(a,b); int i=0,ans=0; while((1<<i)<=n) i++; i--;//減小邊界為2^i-1 int depth=deep[a]-deep[b]; for(int j=i;j>=0;j--) if((1<<j)&depth) {ans=max(ans,mxcost[a][j]);a=p[a][j];}//注意更新的順序 if(b==a) return ans; for(int j=i;j>=0;j--) { if(p[a][j]!=p[b][j]) { ans=max(ans,mxcost[a][j]); ans=max(ans,mxcost[b][j]); a=p[a][j],b=p[b][j]; } } ans=max(ans,mxcost[a][0]); ans=max(ans,mxcost[b][0]); return ans; } //一定要初始化 void init() { memset(e,0,sizeof(e)); memset(edge,0,sizeof(edge)); memset(book,0,sizeof(book)); memset(deep,0,sizeof(deep)); memset(fa,0,sizeof(fa)); memset(head,0,sizeof(head)); memset(mxcost,0,sizeof(mxcost)); memset(cost,0,sizeof(cost)); cnt=0; } int main() { int kase=0; while(cin>>n>>m) { init(); for(int i=1;i<=m;i++) cin>>e[i].from>>e[i].to>>e[i].w; MinTree(); deep[1]=1;fa[1]=-1; DFS(1); /*for(int i=1;i<=4;i++) cout<<deep[i]<<"~"<<i<<"\n";*/ preprocess(); int k;cin>>k; if(++kase!=1) cout<<"\n"; while(k--) { int t1,t2; cin>>t1>>t2; cout<<query(t1,t2)<<"\n"; } } return 0; }