loj#137 最小瓶颈路 加强版
分析
我们知道答案一定再最小生成树上
于是我们按边权从小到大建立kruskal重构树
然后每次查询lca的值即可
由于询问较多采用st表维护lca
代码
格式化代码
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
struct node {
int x,y,z;
};
node d[400100];
vector<int>v[400100];
int lg[400100],A,B,C,P,dep[400100],no[400100];
int pr[400100][23],val[400100],cnt,n,m,q,T,fa[400100];
inline int rnd(){return A=(A*B+C)%P;}
inline int mmin(int x,int y){return dep[x]<dep[y]?x:y;}
inline int sf(int x){return fa[x]==x?x:fa[x]=sf(fa[x]);}
inline bool cmp(const node x,const node y){return x.z<y.z;}
inline int que(int x,int y){int k=lg[y-x+1];return mmin(pr[x][k],pr[y-(1<<k)+1][k]);}
inline void dfs(int x,int f){
dep[x]=dep[f]+1;
pr[++T][0]=x;
no[x]=T;
for(int i=0;i<v[x].size();++i){
dfs(v[x][i],x);
pr[++T][0]=x;
}
}
inline int ra(){
int x=0;char s=getchar();
while(!isdigit(s))s=getchar();
while(isdigit(s))x=(x<<1)+(x<<3)+(s-'0'),s=getchar();
return x;
}
int main(){
int i,j,k,Ans=0;
n=ra(),m=ra();
for(i=1;i<=m;++i)d[i].x=ra(),d[i].y=ra(),d[i].z=ra();
sort(d+1,d+m+1,cmp);
for(i=1;i<=2*n;++i)fa[i]=i;
k=0,cnt=n;
for(i=1;i<=m;++i){
int x=d[i].x,y=d[i].y;
if(sf(x)!=sf(y)){
v[++cnt].push_back(sf(x));
v[cnt].push_back(sf(y));
fa[sf(x)]=fa[sf(y)]=cnt;
val[cnt]=d[i].z;
k++;
}
if(k==n-1)break;
}
dfs(cnt,0);
lg[1]=0;
for(i=2;i<=T;++i)lg[i]=lg[i>>1]+1;
for(i=1;i<=20;++i)
for(j=1;j+(1<<i)<=T;++j)
pr[j][i]=mmin(pr[j+(1<<(i-1))][i-1],pr[j][i-1]);
q=ra(),A=ra(),B=ra(),C=ra(),P=ra();
while(q--){
int x=rnd()%n+1,y=rnd()%n+1;
x=no[x],y=no[y];
if(x>y)swap(x,y);
Ans=Ans+val[que(x,y)];
Ans=(Ans>mod?Ans-mod:Ans);
}
printf("%d\n",Ans);
return 0;
}