zoukankan      html  css  js  c++  java
  • loj2718 「NOI2018」归程[Kruskal重构树+最短路]

    关于Kruskal重构树可以翻阅本人的最小生成树笔记。

    这题明显裸的Kruskal重构树。

    然后这题限制$le p$的边不能走,实际上就是要满足走最小边权最大的瓶颈路,于是跑最大生成树,构建Kruskal重构树。

    通过倍增跳到最浅祖先位置,就get到了一个点可以走到的点集(子树所有叶子)。这些点里选出一个距离$1$最短的。dijkstra。子树维护$min_{dis}$即可。

    复杂度$O(T(Mlog M+Qlog N))$

    注意Kruskal重构树的算法并不是特别容易写对。配合上多测,非常恶心

    Details:

    • line67:合并子树的时候是用根来合并的
    • line65:并查集初始化范围要两倍(所有和重构树有关的变量都要两倍空间)
    • 多测清空,旧病。。$father$需要清空,否则line55出错。
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #define dbg(x) cerr << #x << " = " << x <<endl
     8 #define dbg2(x,y) cerr<< #x <<" = "<< x <<"  "<< #y <<" = "<< y <<endl
     9 using namespace std;
    10 typedef long long ll;
    11 typedef double db;
    12 typedef pair<int,int> pii;
    13 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    14 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    15 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    16 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    17 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    18 template<typename T>inline T read(T&x){
    19     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    20     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    21 }
    22 const int N=2e5+7,INF=0x7a7a7a7a;
    23 int Test,n,m,q,K,S;
    24 struct stothx{int to,nxt,w;}G[N<<2],T[N<<2];
    25 int Head[N],tot;
    26 inline void Addedge(int x,int y,int z){
    27     G[++tot].to=y,G[tot].nxt=Head[x],Head[x]=tot,G[tot].w=z;
    28     G[++tot].to=x,G[tot].nxt=Head[y],Head[y]=tot,G[tot].w=z;
    29 }
    30 priority_queue<pii,vector<pii>,greater<pii> > pq;
    31 int dis[N<<1];
    32 #define y G[j].to
    33 inline void dij(){
    34     memset(dis,0x7a,sizeof dis);pq.push(make_pair(dis[1]=0,1));
    35     while(!pq.empty()){
    36         int d=pq.top().first,x=pq.top().second;pq.pop();
    37         if(d^dis[x])continue;
    38         for(register int j=Head[x];j;j=G[j].nxt)if(MIN(dis[y],d+G[j].w))pq.push(make_pair(dis[y],y));
    39     }
    40 }
    41 #undef y
    42 
    43 int val[N<<1],thead[N<<1],ttot,cnt,fa[N<<1][20],fp[N];
    44 inline void TreeAddedge(int x,int y){
    45     T[++ttot].to=y,T[ttot].nxt=thead[x],thead[x]=ttot;
    46     T[++ttot].to=x,T[ttot].nxt=thead[y],thead[y]=ttot;
    47 }
    48 #define y T[j].to
    49 void dfs(int x,int fat,int d){
    50     fa[x][0]=fat;
    51     for(register int k=1;k<=fp[d];++k)fa[x][k]=fa[fa[x][k-1]][k-1];
    52     for(register int j=thead[x];j;j=T[j].nxt)if(y^fat)dfs(y,x,d+1),MIN(dis[x],dis[y]);
    53 }
    54 #undef y
    55 inline int Query(int v,int p){for(register int k=19;~k;--k)if(val[fa[v][k]]>p)v=fa[v][k];return v;}
    56 //notice that fa[] must be cleared before each test,or errors will occur when k is a litter big,for example k=19,18...
    57 struct thxorz{
    58     int u,v,w;
    59     inline bool operator <(const thxorz&A)const{return w>A.w;}
    60 }e[N<<1];
    61 int anc[N<<1];
    62 inline int getanc(int x){return anc[x]==x?x:anc[x]=getanc(anc[x]);}
    63 inline void ex_kruskal(){
    64     sort(e+1,e+m+1);cnt=n;
    65     for(register int i=1;i<n<<1;++i)anc[i]=i;//notice the range.
    66     for(register int i=1;i<=m;++i)if(getanc(e[i].u)^getanc(e[i].v)){//dbg2(anc[e[i].u],anc[e[i].v]);
    67         val[++cnt]=e[i].w;TreeAddedge(anc[e[i].u],cnt),TreeAddedge(anc[e[i].v],cnt);//notice the vertex:anc[...]
    68         anc[anc[e[i].u]]=anc[anc[e[i].v]]=cnt;//dbg2(i,cnt);
    69     }
    70 }
    71 
    72 int main(){freopen("return.in","r",stdin);freopen("return.out","w",stdout);
    73     for(register int i=1;i<=2e5+5;++i)fp[i]=__lg(i);
    74     read(Test);while(Test--){
    75         read(n),read(m);
    76         int v,p,las=0;
    77         tot=ttot=0,memset(Head,0,sizeof Head),memset(thead,0,sizeof thead),memset(val,0,sizeof val),memset(fa,0,sizeof fa);
    78         for(register int i=1,z;i<=m;++i)read(e[i].u),read(e[i].v),read(z),read(e[i].w),Addedge(e[i].u,e[i].v,z);
    79         dij();ex_kruskal();dfs(2*n-1,0,0);
    80         read(q),read(K),read(S);
    81         while(q--){
    82             read(v),read(p);
    83             v=(v+(K?las:0)-1)%n+1,p=(p+(K?las:0))%(S+1);
    84             printf("%d
    ",las=dis[Query(v,p)]);
    85         }
    86     }
    87     return 0;
    88 }
    View Code

    总结:瓶颈路题不妨试试Kruskal重构树。

    另外再付一道类似的板子题,有空待做。BZOJ3551

  • 相关阅读:
    luogu P1877 [HAOI2012]音量调节
    luogu P1510 精卫填海
    luogu P1508 Likecloud-吃、吃、吃
    我的VIM
    luogu P1310 表达式的值
    luogu P1402 酒店之王
    luogu P3119 [USACO15JAN]草鉴定Grass Cownoisseur
    luogu P1879 [USACO06NOV]玉米田Corn Fields
    luogu P2746 [USACO5.3]校园网Network of Schools
    [BZOJ4870][六省联考2017]组合数问题(组合数动规)
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11679823.html
Copyright © 2011-2022 走看看