LCT——BZOJ3669/Luogu2387 [Noi2014]魔法森林

来源:互联网 发布:名片地图生成软件 编辑:程序博客网 时间:2024/06/05 06:54

题面:BZOJ3669 Luogu2387
LCT维护动态最小生成树
具体怎么操作呢,如果当前加边后树中形成了环,那么就把环上边权最大的边删掉,再把这条边加进去(当然啦如果这条边比环里的边都大就不要加)
这就是维护动态最小生成树,这些操作都可以用LCT来解决
LCT维护边权最大值(只不过维护的时候要记录的是编号)
然后最后答案的话在每次操作之后都询问一下从1到n的最大边权
这个也只要直接access就好了

#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<iostream>#include<cstdlib>#include<string>#include<ctime>#include<queue>#include<climits>using namespace std;struct ppap{int x,y,a,b;}a[100001];inline bool cmp(ppap a,ppap b){return a.a<b.a;}int t[200001][2],fa[200001],la[200001];int n,m,zh[200001],v[200001],s[200001];inline void pushup(int x){    s[x]=x;if(v[s[t[x][0]]]>v[s[x]])s[x]=s[t[x][0]];    if(v[s[t[x][1]]]>v[s[x]])s[x]=s[t[x][1]];}inline void pushdown(int x){    if(la[x]){        swap(t[x][1],t[x][0]);        la[t[x][1]]^=1;la[t[x][0]]^=1;    }    la[x]=0;}inline bool rt(int x){    return t[fa[x]][0]!=x&&t[fa[x]][1]!=x;}inline void turn(int x){    int y=fa[x],z=fa[y],l=(x!=t[fa[x]][0]),r=(y!=t[fa[y]][0]);    int p=t[x][l^1];    if(!rt(y))t[z][r]=x;    fa[p]=y;fa[x]=z;t[x][l^1]=y;fa[y]=x;t[y][l]=p;    pushup(y);pushup(x);}inline void splay(int x){    int i=x,y,z;for(;!rt(i);i=fa[i])zh[++zh[0]]=i;    zh[++zh[0]]=i;while(zh[0])pushdown(zh[zh[0]--]);    while(!rt(x)){        y=fa[x];z=fa[y];        if(!rt(y)){            if((t[y][0]==x)^(t[z][0]==y))turn(x);            else turn(y);        }        turn(x);    }}inline void access(int x){    int p=0;    while(x){        splay(x);t[x][1]=p;        p=x;pushup(x);x=fa[x];    }}inline void chrt(int x){    access(x);splay(x);la[x]^=1;}inline void link(int x,int y){    chrt(x);fa[x]=y;}inline void cut(int x,int y){    chrt(x);access(y);splay(y);    t[y][0]=fa[x]=0;pushup(y);}inline int askrt(int x){    access(x);splay(x);int p=x;pushdown(x);    while(t[p][0])p=t[p][0],pushdown(p);    return p;}int main(){    scanf("%d%d",&n,&m);int ans=1e9;    for(int i=1;i<=m;i++)scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].a,&a[i].b);    sort(a+1,a+m+1,cmp);    for(int i=1;i<=m;i++){        int X=a[i].x,Y=a[i].y,A=a[i].a,B=a[i].b;        if(askrt(X)==askrt(Y)){            chrt(X);access(Y);splay(Y);int p=s[Y];            if(v[p]>B)cut(p,a[p-n].x),cut(p,a[p-n].y);            else{                if(askrt(1)==askrt(n)){                    chrt(1);access(n);splay(n);                    ans=min(ans,A+v[s[n]]);                }                continue;            }        }        v[n+i]=B;s[n+i]=n+i;link(X,n+i);link(Y,n+i);        if(askrt(1)==askrt(n)){            chrt(1);access(n);splay(n);            ans=min(ans,A+v[s[n]]);        }    }    if(ans==1e9)puts("-1");    else printf("%d",ans);    return 0;}
原创粉丝点击