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;
}

 

posted @ 2019-09-19 10:09  水题收割者  阅读(278)  评论(0编辑  收藏  举报