题解:

lct维护最小生成树

首先,先对于每一条边,生成一个点,这个点连接这一条边的两个端点

点的值为边的权值

其他点的权值都是0

那么每一次查找i-j路径上面最小值,就变成查找树上路径点权最小值

按照最小生成树的方法来生成这一刻lct

然后先把所有要删去的边删掉,后面再一条一条加上去

代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int N=2000005;
int n,m,Q,top,f[N],fa[N],c[N][2],s[N],mx[N],val[N],rev[N];
struct edge{int u,v,w,id,d;}e[N/2];
struct que{int f,x,y,ans,id;}q[N/2];
int operator<(edge a,edge b){return a.u<b.u||(a.u==b.u&&a.v<b.v);}
int cmp(edge a,edge b){return a.w<b.w;}
int cmp2(edge a,edge b){return a.id<b.id;}
int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);}
int find(int u,int v)
{
    int l=1,r=m;
    while (l<r)
     {
        int mid=(l+r)/2;
        if (e[mid].u<u||(e[mid].u==u&&e[mid].v<v))l=mid+1;
        else r=mid;
     }
    return l; 
}
int isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
void update(int x)
{
    int l=c[x][0],r=c[x][1];mx[x]=x;
    if(val[mx[l]]>val[mx[x]])mx[x]=mx[l];
    if(val[mx[r]]>val[mx[x]])mx[x]=mx[r];
}
void rotate(int x)
{
    int y=fa[x],z=fa[y],l,r;
    if(c[y][0]==x)l=0;else l=1;r=l^1;
    if (!isroot(y))
      {
        if (c[z][0]==y)c[z][0]=x;
        else c[z][1]=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 pushdown(int x)
{
    int l=c[x][0],r=c[x][1];
    if (rev[x])
     {
        rev[x]^=1;rev[l]^=1;rev[r]^=1;
        swap(c[x][0],c[x][1]);
     }
}
void down(int x)
{
    if (!isroot(x))down(fa[x]);
    pushdown(x);
}
void splay(int x)
{
    down(x);
    for (int y=fa[x];!isroot(x);rotate(x),y=fa[x])
     if (!isroot(y))rotate((c[y][0]==x)==(c[fa[y]][0]==y)?y:x);
}
void access(int x)
{
    int t=0;
    while (x)
     {
        splay(x);
        c[x][1]=t;
        update(x);
        t=x;x=fa[x];
     }
}
void makeroot(int x){access(x);splay(x);rev[x]^=1;}
void link(int x,int y){makeroot(x);fa[x]=y;}
void cut(int x,int y){makeroot(x);access(y);splay(y);c[y][0]=fa[x]=0;}
int query(int x,int y){makeroot(x);access(y);splay(y);return mx[y];}
int read()
{
    int x=0;char c;
    for (;c<'0'||c>'9';c=getchar());
    for (;c>='0'&&c<='9';c=getchar())x=x*10+c-48;
    return x;
}
int main()
{
    n=read();m=read();Q=read();
    for (int i=1;i<=n;i++)f[i]=i;
    for (int i=1;i<=m;i++)
     {
        e[i].u=read(),e[i].v=read(),e[i].w=read();
        if (e[i].u>e[i].v)swap(e[i].u,e[i].v);
     }
    sort(e+1,e+m+1,cmp);
    for (int i=1;i<=m;i++)
     {
        e[i].id=i;
        val[n+i]=e[i].w;    
        mx[n+i]=n+i;
     }
    sort(e+1,e+m+1);
    for (int i=1;i<=Q;i++)
     {
        q[i].f=read(),q[i].x=read(),q[i].y=read();
        if (q[i].f==2)
         {
            if(q[i].x>q[i].y)swap(q[i].x,q[i].y);
            int t=find(q[i].x,q[i].y);
            e[t].d=1;q[i].id=e[t].id;
         }
     }
    sort(e+1,e+m+1,cmp2);
    int tot=0;
    for (int i=1;i<=m;i++)
     if (!e[i].d)
      {
         int u=e[i].u,v=e[i].v,x=getf(u),y=getf(v);
        if (x!=y)
         {
             f[x]=y;
            link(u,i+n);
            link(v,i+n);
         }
      }
    for (int i=Q;i;i--)
     {
         int u=q[i].x,v=q[i].y,k=q[i].id;
        if(q[i].f==1)q[i].ans=val[query(u,v)];
        else
         {
            int t=query(u,v);
            if(e[k].w<val[t])
             {
                cut(e[t-n].u,t);cut(e[t-n].v,t);
                link(u,k+n);link(v,k+n);             
             }    
         }
     }
    for (int i=1;i<=Q;i++)
     if (q[i].f==1)printf("%d\n",q[i].ans); 
    return 0;
}

 

posted on 2017-12-12 19:47  宣毅鸣  阅读(83)  评论(0编辑  收藏  举报