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

来自FallDream的博客,未经允许,请勿转载,谢谢。


简要题意:给定一张n个点m条边的图,有边权,需要支持两个操作 1)删除一条边2)求两点之间边权最大值的最小值   n和操作次数不超过10^5,m<=10^6
题解:很显然要你维护的是一个最小生成树qaq
然后删边太难了,考虑倒过来加边,用边权lct维护最小生成树。每个点维护向父亲和偏爱儿子的连边的编号,还有他所在的splay的最左边和最右边的那条边(不懂边权lct可以自行百度)
假设你要插入边u->v,如果它们不连通,直接插入。不然的话,如果u->v的路径上的边权的最大值超过了这条边的边权,删掉最大的那条边,加入这条边就行了。
lct常数巨大  所以一开始把没被删除的边插入的时候不能lct,要用kruscal,不然T的飞起。
#include<iostream>
#include<cstdio>
#include<algorithm>
#define MN 100000
#define INF 2000000000
#define getchar() (*S++) 
using namespace std;
char B[1<<26],*S=B;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}

int n,m,Q,rk[MN*10+5],fa[MN+5],qu[MN+5],top,c[MN+5][2],mx[MN+5],s[MN+5],p[MN+5],f[MN+5],L[MN+5],R[MN+5],ans[MN+5];
bool rev[MN+5],mark[MN*10+5];
struct edge{int from,to,w,num;
    bool operator<(const edge&b)const{return from==b.from?to<b.to:from<b.from;}
}e[MN*10+5];
struct ques{int kind,x,y;}q[MN+5];

inline bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
inline void pushdown(int x)
{
    if(rev[x])
    {
        int l=c[x][0],r=c[x][1];
        rev[l]^=1;rev[r]^=1;rev[x]^=1;
        swap(c[x][0],c[x][1]);
        swap(L[l],R[l]);swap(f[l],p[l]);
        swap(L[r],R[r]);swap(f[r],p[r]); 
    }
}
inline void U(int&x,int y){if(e[x].w<e[y].w) x=y;}
inline void update(int x)
{
    mx[x]=(e[f[x]].w>e[p[x]].w)?f[x]:p[x];
    L[x]=f[x];R[x]=p[x];
    int l=c[x][0],r=c[x][1];
    if(l) L[x]=L[l],U(mx[x],mx[l]),U(mx[x],p[l]);
    if(r) R[x]=R[r],U(mx[x],mx[r]),U(mx[x],f[r]); 
}

void rotate(int x)
{
    int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
    if(!isroot(y)) c[z][c[z][1]==y]=x;
    fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
    c[y][l]=c[x][r];c[x][r]=y;
    update(y);update(x);
}

void splay(int x)
{
    qu[top=1]=x;
    for(int t=x;!isroot(t);t=fa[t]) qu[++top]=fa[t];
    for(;top;--top) pushdown(qu[top]);
    for(;!isroot(x);rotate(x))
        if(!isroot(fa[x])) rotate((c[fa[fa[x]]][1]==fa[x]^c[fa[x]][1]==x)?x:fa[x]);
}

void access(int x)
{
    for(int y=0;x;x=fa[y=x])
        splay(x),c[x][1]=y,p[x]=L[y],update(x);
}

void link(int x,int y,int z)
{
    access(x);splay(x);rev[x]^=1;swap(f[x],p[x]);swap(L[x],R[x]); 
    access(y);fa[c[y][1]=x]=y;f[x]=p[y]=z;
    update(x);update(y);
}

void cut(int x,int y)
{
    access(x);splay(x);rev[x]^=1;swap(f[x],p[x]);swap(L[x],R[x]); 
    access(y);splay(y);c[y][0]=fa[x]=f[y]=p[x]=0;
    update(x);update(y);
}

void ins(int id)
{
    int x=e[id].from,y=e[id].to,z=e[id].w;
    access(x);splay(x);rev[x]^=1;swap(f[x],p[x]);swap(L[x],R[x]); 
    access(y);splay(y);
    if(isroot(x)) link(x,y,id);
    else if(e[mx[y]].w>z) cut(e[mx[y]].from,e[mx[y]].to),link(x,y,id);
}

inline int getfa(int x){return !s[x]?x:s[x]=getfa(s[x]);}
bool cmp(int x,int y){return e[x].w<e[y].w;}
int main()
{
    fread(B,1,1<<26,stdin);
    e[0].w=-INF;
    n=read();m=read();Q=read();
    for(register int i=1;i<=m;i++) 
    {
        e[i].from=read(),e[i].to=read(),e[i].w=read();
        if(e[i].from>e[i].to) swap(e[i].from,e[i].to);
    }
    sort(e+1,e+m+1);
    for(int i=1;i<=m;i++) rk[i]=i;
    for(register int i=1;i<=Q;i++)
    {
        q[i].kind=read();q[i].x=read();q[i].y=read();
        if(q[i].kind==2) 
        {
            if(q[i].x>q[i].y) swap(q[i].x,q[i].y);
            q[i].x=lower_bound(e+1,e+m+1,(edge){q[i].x,q[i].y,0})-e;    
            mark[q[i].x]=1;
        }
    }
    sort(rk+1,rk+m+1,cmp);
    for(register int i=1;i<=m;i++)
        if(!mark[rk[i]])
        {
            int x=getfa(e[rk[i]].from),y=getfa(e[rk[i]].to);
            if(x!=y) s[x]=y,link(e[rk[i]].from,e[rk[i]].to,rk[i]);
        }
    for(register int i=Q;i;i--)
        if(q[i].kind==2) ins(q[i].x);
        else
        {
            int x=q[i].x,y=q[i].y;
            access(x);splay(x);rev[x]^=1;swap(f[x],p[x]);swap(L[x],R[x]); 
            access(y);splay(y);
            ans[i]=e[mx[y]].w;
        }
    for(register int i=1;i<=Q;i++)
        if(q[i].kind<2) printf("%d\n",ans[i]);
    return 0;
}

 

 

FallDream代表秋之国向您问好! 欢迎您来我的博客www.cnblogs.com/FallDream
posted @ 2017-04-19 08:46  FallDream  阅读(231)  评论(0编辑  收藏  举报