zoukankan      html  css  js  c++  java
  • cogs1685 【NOI2014】魔法森林 Link-Cut Tree

    LCT练手好题啊。
    SPFA的做♂FA是把边按照a排序,然后加一条权值为b的边跑SPFA,不断更新答案。很好的做♂FA,但复杂度无♂FA保证。
    LCT的做♂FA类似,也是把边按照a排序,然后也是加一条权值为b的边,动态维护最小生成树。
    然后赋边权的方♂FA是新建一个点表示边,原来点的权值为0,边的权值还是边的权值,剩下的都一样辣。

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #define il inline
    #define rg register
    #define vd void
    #define sta static
    typedef int mainint;
    #define int long long
    il int gi(){
    	rg int x=0,f=1;rg char ch=getchar();
    	while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*f;
    }
    const int maxn=100001,maxm=100001;
    namespace LCT{
    	int ch[maxn][2],fa[maxn],w[maxn],mx[maxn],A[maxn],B[maxn];bool rev[maxn];
    	int index;
    	il vd down(const int&x){if(rev[x])std::swap(ch[x][0],ch[x][1]),rev[ch[x][0]]^=1,rev[ch[x][1]]^=1,rev[x]=0;}
    	il vd upd(const int&x){
    		mx[x]=x;
    		if(w[mx[x]]<w[mx[ch[x][0]]])mx[x]=mx[ch[x][0]];
    		if(w[mx[x]]<w[mx[ch[x][1]]])mx[x]=mx[ch[x][1]];
    	}
    	il bool isrt(const int&x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    	il vd rotate(const int&x){
    		sta int y,z,o;y=fa[x],z=fa[y],o=x==ch[y][1];
    		if(!isrt(y))ch[z][y==ch[z][1]]=x;fa[x]=z;
    		ch[y][o]=ch[x][!o];fa[ch[x][!o]]=y;
    		fa[y]=x;ch[x][!o]=y;
    		upd(y);
    	}
    	il vd splay(const int&x){
    		sta int stk[maxn],top;stk[top=1]=x;
    		for(rg int i=x;!isrt(i);i=fa[i])stk[++top]=fa[i];
    		while(top)down(stk[top--]);
    		for(rg int y=fa[x],z=fa[y];!isrt(x);rotate(x),y=fa[x],z=fa[y])
    			if(!isrt(y))rotate(((x==ch[y][1])==(y==ch[z][1]))?y:x);
    		upd(x);
    	}
    	il vd access(int x){for(rg int y=0;x;x=fa[y=x])splay(x),ch[x][1]=y,upd(x);}
    	il vd makert(const int&x){access(x),splay(x);rev[x]^=1;}
    	il int find(int x){access(x),splay(x);while(ch[x][0])x=ch[x][0];return x;}
    	il vd split(const int&x,const int&y){makert(x);access(y),splay(y);}
    	il vd _link(const int&x,const int&y){makert(x),fa[x]=y;}
    	il vd cut(const int&x,const int&y){split(x,y);fa[x]=ch[y][0]=0;}
    	il vd link(const int&x,const int&y,const int&k){
    		if(find(x)^find(y)){w[++index]=k,_link(A[index]=x,index),_link(B[index]=y,index);return;}
    		split(x,y);
    		sta int s;s=mx[y];
    		if(w[s]<=k)return;
    		cut(s,A[s]),cut(s,B[s]);
    		w[s]=k,_link(A[s]=x,s),_link(B[s]=y,s);
    	}
    	il int query(int x,int y){
    		if(find(x)^find(y))return 1e18;
    		split(x,y);return w[mx[y]];
    	}
    }
    struct edge{int x,y,a,b;}E[maxm];
    bool operator <(const edge&a,const edge&b){return a.a<b.a;}
    mainint main(){
    	freopen("magicalforest.in","r",stdin);
    	freopen("magicalforest.out","w",stdout);
    	int n=gi(),m=gi();
    	for(rg int i=1;i<=m;++i)E[i].x=gi(),E[i].y=gi(),E[i].a=gi(),E[i].b=gi();
    	std::sort(E+1,E+m+1);
    	int ans=1e18;
    	LCT::index=n;
    	for(rg int i=1;i<=m;++i)LCT::link(E[i].x,E[i].y,E[i].b),ans=std::min(ans,E[i].a+LCT::query(1,n));
    	if(ans==1e18)ans=-1;printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    POJ 2018 二分
    873. Length of Longest Fibonacci Subsequence
    847. Shortest Path Visiting All Nodes
    838. Push Dominoes
    813. Largest Sum of Averages
    801. Minimum Swaps To Make Sequences Increasing
    790. Domino and Tromino Tiling
    764. Largest Plus Sign
    Weekly Contest 128
    746. Min Cost Climbing Stairs
  • 原文地址:https://www.cnblogs.com/xzz_233/p/cogs1685.html
Copyright © 2011-2022 走看看