zoukankan      html  css  js  c++  java
  • 【BZOJ3669】【NOI2014】—魔法森林(LCT维护最小生成树)

    传送门

    aa排序,此时我们所关注的就是1~n路径上bb的最大值

    考虑维护一个bb的最小生成树,实际上就是连了一条边之后找到路径上的最大值看是否更优
    更新一下答案就是了

    注意LctLct无法维护边权
    要把边变成点

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
    	return res*f;
    } 
    const int N=150005;
    int a[N];
    #define lc(u) son[u][0]
    #define rc(u) son[u][1]
    namespace Lct{
    	int q[N],son[N][2],rev[N],fa[N],mx[N];
    	inline bool isrc(int u){
    		return rc(fa[u])==u;
    	}
    	inline bool isrt(int u){
    		if(!fa[u])return 1;
    		return lc(fa[u])!=u&&rc(fa[u])!=u;
    	}
    	inline void pushup(int u){
    		mx[u]=u;
    		if(a[mx[lc(u)]]>a[mx[u]])mx[u]=mx[lc(u)];
    		if(a[mx[rc(u)]]>a[mx[u]])mx[u]=mx[rc(u)];
    	}
    	inline void pushdown(int u){
    		if(!rev[u])return;
    		swap(lc(u),rc(u));		
    		if(lc(u))rev[lc(u)]^=1;
    		if(rc(u))rev[rc(u)]^=1;
    		rev[u]=0;
    	}
    	inline void rotate(int v){
    		int u=fa[v],z=fa[u];
    		int t=rc(u)==v;
    		if(!isrt(u))son[z][rc(z)==u]=v;
    		fa[v]=z;
    		son[u][t]=son[v][t^1],fa[son[v][t^1]]=u;
    		son[v][t^1]=u,fa[u]=v;
    		pushup(u),pushup(v);
    	}
    	inline void splay(int u){
    		q[q[0]=1]=u;
    		for(int v=u;!isrt(v);v=fa[v])q[++q[0]]=fa[v];
    		for(int i=q[0];i;i--)pushdown(q[i]);
    		while(!isrt(u)){
    			if(!isrt(fa[u])){
    				if(isrc(u)==isrc(fa[u]))rotate(fa[u]);
    				else rotate(u);
    			}
    			rotate(u);
    		}
    		pushup(u);
    	}
    	inline void access(int u){
    		for(int v=0;u;v=u,u=fa[u]){
    			splay(u),rc(u)=v;
    			if(v)fa[v]=u;
    			pushup(u);
    		}
    	}
    	inline int findrt(int u){
    		access(u),splay(u);
    		while(pushdown(u),lc(u))u=lc(u);
    		splay(u);return u;
    	}
    	inline void makert(int u){
    		access(u),splay(u),rev[u]^=1;
    	}
    	inline void link(int u,int v){
    		makert(u),fa[u]=v;
    	}
    	inline void cut(int u,int v){
    		makert(u),access(v),splay(v);
    		lc(v)=fa[u]=0,pushup(v);
    	}
    	inline int query(int u,int v){
    		makert(u),access(v),splay(v);return mx[v];
    	}
    }
    using namespace Lct;
    struct edge{
    	int u,v,a,b;
    }e[N];
    inline bool comp(const edge &a,const edge &b){
    	return a.a==b.a?a.b<b.b:a.a<b.a;
    }
    int f[N];
    int n,m;
    inline int find(int x){
    	return f[x]==x?x:f[x]=find(f[x]);
    }
    int main(){
    	n=read(),m=read();int ans=1e9;
    	for(int i=1;i<=m;i++){
    		e[i].u=read(),e[i].v=read();
    		e[i].a=read(),e[i].b=read();
    	}
    	for(int i=1;i<=n;i++)f[i]=i;
    	sort(e+1,e+m+1,comp);
    	for(int i=1;i<=m;i++){
    		int u=e[i].u,v=e[i].v;
    		int f1=find(u),f2=find(v);
    		if(f1==f2){
    			int k=query(u,v);
    			if(a[k]<=e[i].b)continue;
    			cut(k,e[k-n].u),cut(k,e[k-n].v);
    		}
    		else f[f1]=f2;
    		a[n+i]=e[i].b,mx[n+i]=n+i;
    		link(u,n+i),link(v,n+i);
    		if(find(1)==find(n))ans=min(ans,e[i].a+a[query(1,n)]);
    	}
    	if(ans==1e9)ans=-1;
    	cout<<ans;
    }
    
    
  • 相关阅读:
    12-单表查询
    11-数据的增删改
    10-外键的变种 三种关系
    09-完整性约束
    08-数据类型(2)
    07-数据类型
    06-表的操作
    05-库的操作
    Spring:(六) 代理模式
    Spring:(五) 注解
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145607.html
Copyright © 2011-2022 走看看