最小生成树

3月27 日生日(华理)。

4月1  ‘日’蓝桥杯(华师);

4月15‘日’金马五校(上大?)。

蓝桥杯一定要稳住啊,毕竟准备了这么久,手感一直还不错;但求小题(补齐代码)里面不要考指针。

蓝桥杯在华师,比完去献血-------纪念一下。

五校要被大佬吊打啦。。。啦啦啦。只求rp++得个二等奖啊。

4-16日,开始预习前面落下的功课,尽量不挂科吧。

(4-3日:蓝桥杯手感很好,打完感觉140分稳了。但是后来发现读错了一题,扣了21分。所以120分,与一等奖无缘。

--------------------------------------------分界线---------------------------------------------

对于最小生成树的两条结论。

例题1:

        给定N个点M条边的连通图,每个点有自己的颜色(W或R),现在有节点颜色更改操作;和询问操作,需要回答最近的异色点对的距离。

结论1:

        异色最近点对一定在最小生成树上的边的端点。

例题2:

       给定N个点M条边的连通图,边上有边权,现在给定若干个询问。每次询问给出u,v,需要求出u到v的所有路径最大边的最小值。

结论2:

      求出最小生成树,那么是生成树上u到v的路径上的最大值(树剖可得)就是所求。

BZOJ3732:用动态树维护的最小生成树(当然也可能是森林)

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=50010;
struct egde{
    int x,y,val;
}e[maxn];
void read(int &x){
    char c=getchar(); x=0;
    for(;c>'9'||c<'0';c=getchar());
    for(;c<='9'&&c>='0';c=getchar()) x=(x<<3)+(x<<1)+c-'0';
}
struct LCT
{
    int Max[maxn],rev[maxn],ch[maxn][2],fa[maxn],stc[maxn],top;
    int isroot(int x){
        return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
    }
    int get(int x){
        return ch[fa[x]][1]==x;
    }
    void pushdown(int x)
    {
        if(!rev[x]||!x) return ;
        swap(ch[x][0],ch[x][1]);
        if(ch[x][0]) rev[ch[x][0]]^=1; 
        if(ch[x][1]) rev[ch[x][1]]^=1; 
        rev[x]=0;
    }
    void pushup(int x)
    {
        Max[x]=x;
        if(ch[x][0]&&e[Max[ch[x][0]]].val>e[Max[x]].val) Max[x]=Max[ch[x][0]];
        if(ch[x][1]&&e[Max[ch[x][1]]].val>e[Max[x]].val) Max[x]=Max[ch[x][1]];
    }
    void rotate(int x)
    {
        int old=fa[x],fold=fa[old],opt=get(x);
        if(!isroot(old)) ch[fold][get(old)]=x;
        fa[x]=fold;
        ch[old][opt]=ch[x][opt^1]; fa[ch[old][opt]]=old;
        ch[x][opt^1]=old; fa[old]=x; 
        pushup(old); pushup(x);
    }
    void splay(int x)
    {
        int top=0; stc[++top]=x;
        for(int i=x;!isroot(i);i=fa[i]) stc[++top]=fa[i];
        for(int i=top;i;i--) pushdown(stc[i]);
        for(int f;!isroot(x);rotate(x)){
            if(!isroot(f=fa[x]))
              rotate(get(x)==get(f)?f:x);
        }        
    }
    void access(int x)
    {
        int rson=0;
        for(;x;rson=x,x=fa[x]){
            splay(x);
            ch[x][1]=rson;
            pushup(x);
        }
    }
    int find(int x){ access(x); splay(x); while(ch[x][0]) x=ch[x][0]; return x;}
    int query(int x,int y) { make_root(y); access(x);  splay(x); return Max[x]; }
    void make_root(int x) { access(x); splay(x); rev[x]^=1; }
    void link(int x,int y) { make_root(x); fa[x]=y; splay(x); }
    void cut(int x,int y) { make_root(x); access(y); splay(y); fa[x]=ch[y][0]=0; }    
    
}S;
int main()
{
    int N,M,Q,u,v,i;
    scanf("%d%d%d",&N,&M,&Q);
    for(i=1;i<=M;i++){
         read(e[i].x); read(e[i].y) ;read(e[i].val);
         if(S.find(M+e[i].x)!=S.find(M+e[i].y)){
             S.link(i,M+e[i].x); S.link(i,M+e[i].y);
         }
         else {
             int tmp=S.query(M+e[i].x,M+e[i].y);
             if(e[tmp].val>e[i].val){
                 S.cut(tmp,M+e[tmp].x); S.cut(tmp,M+e[tmp].y);
                 S.link(i,M+e[i].x); S.link(i,M+e[i].y);
             }
         } 
    }
    while(Q--){
        read(u); read(v);
        printf("%d
",e[S.query(M+u,M+v)].val);
    }
    return 0;
}

 (上面两个都可以通过反证得到)。

原文地址:https://www.cnblogs.com/hua-dong/p/8659796.html