luogu2387 [NOI2014]魔法森林

这题和水管局长很像,枚举 \(a\) 的边然后维护关于 \(b\) 的最小生成树就可以了。
1A呐>_<

#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
int n, m, val[150005], zdz[150005], ans=0x3f3f3f3f, fa[150005];
int ch[150005][2], rev[150005];
struct Edge{
    int fro, too, vaa, vab;
}edge[100005];
bool cmp(Edge x, Edge y){
    return x.vaa<y.vaa;
}
void upd(int x){
    zdz[x] = val[x];
    if(edge[zdz[ch[x][0]]].vab>edge[zdz[x]].vab)
        zdz[x] = zdz[ch[x][0]];
    if(edge[zdz[ch[x][1]]].vab>edge[zdz[x]].vab)
        zdz[x] = zdz[ch[x][1]];
}
int getw(int x){
    return ch[fa[x]][1]==x;
}
bool isroot(int x){
    return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
}
void pushdown(int x){
    if(rev[x]){
        swap(ch[x][0], ch[x][1]);
        rev[ch[x][0]] ^= 1;
        rev[ch[x][1]] ^= 1;
        rev[x] = false;
    }
}
void xf(int x){
    if(fa[x])   xf(fa[x]);
    pushdown(x);
}
void rotate(int x){
    int old=fa[x], oldf=fa[old], w=getw(x);
    if(!isroot(old))    ch[oldf][ch[oldf][1]==old] = x;
    ch[old][w] = ch[x][w^1]; ch[x][w^1] = old;
    fa[ch[old][w]] = old; fa[ch[x][w^1]] = x; fa[x] = oldf;
    upd(old); upd(x);
}
void splay(int x){
    xf(x);
    while(!isroot(x)){
        int f=fa[x];
        if(!isroot(f))  rotate(getw(f)==getw(x)?f:x);
        rotate(x);
    }
    upd(x);
}
void access(int x){
    int y=0;
    while(x){
        splay(x);
        ch[x][1] = y;
        upd(x);
        y = x;
        x = fa[x];
    }
}
void makeroot(int x){
    access(x);
    splay(x);
    rev[x] ^= 1;
}
int findroot(int x){
    access(x);
    splay(x);
    while(ch[x][0])
        x = ch[x][0];
    splay(x);
    return x;
}
void split(int x, int y){
    makeroot(x);
    access(y);
    splay(y);
}
void link(int x, int y){
    makeroot(x);
    fa[x] = y;
}
void cut(int x, int y){
    split(x, y);
    fa[x] = ch[y][0] = 0;
}
int main(){
    cin>>n>>m;
    for(int i=1; i<=m; i++){
        scanf("%d %d %d %d", &edge[i].fro, &edge[i].too, &edge[i].vaa, &edge[i].vab);
        if(edge[i].fro>edge[i].too)    swap(edge[i].fro, edge[i].too);
    }
    for(int i=n+1; i<=n+m; i++)
        val[i] = zdz[i] = i - n;
    sort(edge+1, edge+1+m, cmp);
    int j=1;
    for(int i=1; i<=50000; i++){
        for(; j<=m && edge[j].vaa<=i; j++){
            int x=edge[j].fro, y=edge[j].too;
            if(findroot(x)!=findroot(y)){
                link(x, j+n);
                link(y, j+n);
            }
            else{
                split(x, y);
                int idx=zdz[y];
                if(edge[j].vab<edge[idx].vab){
                    cut(edge[idx].fro, idx+n);
                    cut(edge[idx].too, idx+n);
                    link(edge[j].fro, j+n);
                    link(edge[j].too, j+n);
                }
            }
        }
        if(findroot(1)==findroot(n)){
            split(1, n);
            ans = min(ans, i+edge[zdz[n]].vab);
        }
    }
    if(ans!=0x3f3f3f3f) printf("%d\n", ans);
    else    printf("%d\n", -1);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/poorpool/p/9114726.html