bzoj2594: [Wc2006]水管局长数据加强版

居然1A,思路清晰的好处。

题目不再解释;

题目要求维护两点间最小的路径所经过边的权值最大值,很显然,这东西肯定是在MST上;

Kruskal跑出MST,就可以在树上随便搞;

但题目有删边要求,删边不好做,干脆反过来做成加边;

用LCT维护一下两点间最大的边就好了;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<algorithm>
using namespace std;
#define mid ((l+r)>>1)
#define LL long long
#define FILE "dealing"
#define up(i,j,n) for(LL i=(j);i<=(n);i++)
#define pii pair<int,int>
int read(){
    int x=0,f=1,ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    return f*x;
}
const int maxn=300010,inf=100000000,mod=998244353;
int n,m,q;
struct edge{int x,y,v;}b[1001000];
bool cmp(edge a,edge b){return a.v<b.v;}
struct node{int y,next,v;}e[2000000],k[2000000];
int len,linkk[2000000],cnt,Link[2000000],fa[maxn],x[maxn],y[maxn],ans[maxn],Max[maxn],cnt_point,w[maxn],f[maxn][2],val[maxn];
void insert(node* e,int* linkk,int& len,int x,int y,int v){e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;e[len].v=v;}
int ch[maxn],u[maxn],v[maxn];
namespace Kruskal{
    int fa[maxn];
    int getfa(int x){return x==fa[x]?x:fa[x]=getfa(fa[x]);}
    void kruskal(){
        cnt_point=n;
        bool flag=0;
        up(i,1,n)fa[i]=i;
        up(i,1,m){
            flag=0;
            for(int j=Link[b[i].x];j;j=k[j].next)
                if(k[j].y==b[i].y){
                    val[k[j].v]=b[i].v;
                    flag=1;
                    break;
                }
            for(int j=Link[b[i].y];j;j=k[j].next)
                if(k[j].y==b[i].x){
                    val[k[j].v]=b[i].v;
                    flag=1;
                    break;
                }
            if(flag)continue;
            getfa(b[i].x),getfa(b[i].y);
            if(fa[b[i].x]==fa[b[i].y])continue;
            fa[b[i].x]=fa[b[i].y];
            cnt_point++;
            f[cnt_point][0]=b[i].x,f[cnt_point][1]=b[i].y;
            insert(e,linkk,len,b[i].x,cnt_point,b[i].v);
            insert(e,linkk,len,cnt_point,b[i].x,b[i].v);
            insert(e,linkk,len,b[i].y,cnt_point,b[i].v);
            insert(e,linkk,len,cnt_point,b[i].y,b[i].v);
        }
    }
};
namespace DFS{
    void dfs(int x){
        for(int i=linkk[x];i;i=e[i].next){
            if(e[i].y==fa[x])continue;
            if(x>n)w[x]=e[i].v;
            Max[x]=x;
            fa[e[i].y]=x;
            dfs(e[i].y);
        }
    }
};
namespace LCT{
    int c[maxn][2],rev[maxn],q[maxn],top;
    void reve(int o){rev[o]^=1,swap(c[o][0],c[o][1]);}
    void pushdown(int o){if(rev[o])reve(c[o][0]),reve(c[o][1]),rev[o]^=1;}
    void updata(int o){
        Max[o]=o;
        if(w[Max[c[o][1]]]>w[Max[o]])Max[o]=Max[c[o][1]];
        if(w[Max[c[o][0]]]>w[Max[o]])Max[o]=Max[c[o][0]];
    }
    bool isroot(int o){return c[fa[o]][0]!=o&&c[fa[o]][1]!=o;}
    void rotate(int x){
        int y=fa[x],z=fa[y],d=(c[y][1]==x);
        if(!isroot(y))c[z][c[z][1]==y]=x;
        fa[y]=x;fa[x]=z;fa[c[x][d^1]]=y;
        c[y][d]=c[x][d^1];c[x][d^1]=y;
        updata(y),updata(x);
    }
    void splay(int x){
        q[++top]=x;
        for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
        while(top)pushdown(q[top--]);
        while(!isroot(x)){
            int y=fa[x],z=fa[y];
            if(!isroot(y)){
                if(c[y][1]==x^c[z][1]==y)rotate(x);
                else rotate(y);
            }
            rotate(x);
        }
    }
    void access(int x){
        for(int t=0;x;t=x,x=fa[x])
            splay(x),c[x][1]=t,updata(x);
    }
    void makeroot(int x){
        access(x);splay(x);reve(x);
    }
    void cut(int x,int y){
        makeroot(x);access(y);splay(y);c[y][0]=fa[x]=0;updata(y);
    }
    void link(int x,int y){
        makeroot(x);fa[x]=y;
    }
};
int main(){
    freopen(FILE".in","r",stdin);
    freopen(FILE".out","w",stdout);
    n=read(),m=read(),q=read();
    up(i,1,m)b[i].x=read(),b[i].y=read(),b[i].v=read();
    sort(b+1,b+m+1,cmp);
    up(i,1,q)ch[i]=read(),x[i]=read(),y[i]=read();
    up(i,1,q)if(ch[i]==2){
        insert(k,Link,cnt,x[i],y[i],i);
        insert(k,Link,cnt,y[i],x[i],i);
    }
    Kruskal::kruskal();
    DFS::dfs(1);
    for(int i=q;i>0;i--){
        if(ch[i]==1){
            LCT::makeroot(x[i]),LCT::access(y[i]),LCT::splay(y[i]);
            ans[i]=w[Max[y[i]]];
        }
        if(ch[i]==2){
            LCT::makeroot(x[i]),LCT::access(y[i]),LCT::splay(y[i]);
            int t=Max[y[i]];
            if(val[i]<w[t]){
                LCT::cut(f[t][0],t);LCT::cut(f[t][1],t);
                cnt_point++;
                f[cnt_point][0]=x[i],f[cnt_point][1]=y[i];
                w[cnt_point]=val[i];
                LCT::link(x[i],cnt_point);
                LCT::link(y[i],cnt_point);
            }
        }
    }
    up(i,1,q)if(ch[i]==1)printf("%d\n",ans[i]);
    return 0;
}
View Code

 

posted @ 2017-01-21 17:17  CHADLZX  阅读(253)  评论(0编辑  收藏  举报