zoukankan      html  css  js  c++  java
  • 【bzoj3669】魔法森林

    Portal-->bzoj3669

    Solution

    ​   愉悦智力康复ing

    ​​   这题的话有两个比较关键的地方

    ​​   首先是答案肯定是原图的某个生成树上的一条路径,那么我们考虑怎么来找这个生成树,因为关键值有两个,所以我们这里可以采取这样的一个方式:先对其中一个关键值排序

    ​​   我们先将所有的边按照(a)值排序,然后按顺序加边,如果说当前这条边连接的两个点已经连通了,那么我们要考虑删掉一条边或者干脆不加这条边

    ​   这里我们可以用一个贪心的思想,删边的话肯定是删当前的边中(b)最大的那个(如果要加的那条边的(b)是最大的那么我们就不加这条边),如果说我们加了这条边并且(1)(n)连通了,那么可以用当前最大的(b)+当前的(a)来更新答案(因为(a)是升序排列的,所以当前的(a)一定是最大的)

    ​​   接着是第二部分,如何维护(b)的最大值?

    ​​   又要删边又要加边的维护的又是链的数据,那当然是LCT咯qwq,但是因为这个地方我们是要维护边权,所以我们将每一条边变成一个点,然后其他的就全部都是常规操作了ovo

    ​​   好像是比较套路的一题qwq

    ​  

    ​​   代码大概长这个样子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define mp make_pair
    #define Pr pair<int,int>
    using namespace std;
    const int N=50010,M=100010,L=N+M;
    const int inf=2147483647;
    struct Rec{
    	int a,b,x,y,id;
    	friend bool operator <(Rec x,Rec y){return x.a<y.a;}
    }a[M];
    int n,m,ans;
    namespace Lct{/*{{{*/
    	int ch[L][2],fa[L],mx[L],loc[L],rev[L];
    	int b[L];
    	int tot;
    	bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    	int which(int x){return ch[fa[x]][1]==x;}
    	void reverse(int x){
    		swap(ch[x][0],ch[x][1]);
    		rev[x]^=1;
    	}
    	void pd(int x){
    		if (rev[x]){
    			if (ch[x][0]) reverse(ch[x][0]);
    			if (ch[x][1]) reverse(ch[x][1]);
    			rev[x]=0;
    		}
    	}
    	void pushdown(int x){
    		if (!isroot(x)) pushdown(fa[x]);
    		pd(x);
    	}
    	void pushup(int x){
    		mx[x]=b[x]; loc[x]=x;
    		if (ch[x][0]){
    			if (mx[ch[x][0]]>mx[x])
    				mx[x]=mx[ch[x][0]],loc[x]=loc[ch[x][0]];
    		}
    		if (ch[x][1]){
    			if (mx[ch[x][1]]>mx[x])
    				mx[x]=mx[ch[x][1]],loc[x]=loc[ch[x][1]];
    		}
    	}
    	void rotate(int x){
    		int dir=which(x),f=fa[x];
    		if (!isroot(f)) ch[fa[f]][which(f)]=x;
    		if (ch[x][dir^1]) fa[ch[x][dir^1]]=f;
    		fa[x]=fa[f];
    		ch[f][dir]=ch[x][dir^1];
    		ch[x][dir^1]=f; fa[f]=x;
    		pushup(f);
    		pushup(x);
    	}
    	void splay(int x){
    		pushdown(x);
    		for (int f=fa[x];!isroot(x);f=fa[x]){
    			if (!isroot(f))
    				rotate(which(f)==which(x)?f:x);
    			rotate(x);
    		}
    	}
    	void access(int x){
    		for (int last=0;x;last=x,x=fa[x]){
    			splay(x);
    			ch[x][1]=last;
    			pushup(x);
    		}
    	}
    	void make_rt(int x){
    		access(x);
    		splay(x);
    		reverse(x);
    	}
    	bool connected(int x,int y){
    		if (x==y) return true;
    		make_rt(x);
    		access(y);
    		splay(y);
    		return fa[x];
    	}
    	bool check(int x,int y){
    		make_rt(x);
    		access(y);
    		splay(y);
    		return ch[y][0]==x;
    	}
    	void cut(int x,int y){
    		//printf("Cut %d %d
    ",x,y);
    		make_rt(x);
    		access(y);
    		splay(y);
    		fa[x]=0;
    		ch[y][0]=0;
    		pushup(y);
    	}
    	Pr query(int x,int y){
    		make_rt(x);
    		access(y);
    		splay(y);
    		return mp(mx[y],loc[y]);
    	}
    	void link(int x,int y){
    		//printf("Link %d %d
    ",x,y);
    		make_rt(y);
    		fa[y]=x;
    		pushup(x);
    	}
    	void Link(int x,int y,int bian,int vala){
    		int tmp;
    		if (x==y) return;
    		if (connected(x,y)){
    			tmp=query(x,y).second;
    			if (b[bian]<b[tmp]){
    				cut(a[tmp-n].x,tmp);
    				cut(a[tmp-n].y,tmp);
    				link(x,bian);
    				link(y,bian);
    			}
    		}
    		else{
    			link(x,bian);
    			link(y,bian);
    		}
    		if (connected(1,n)){
    			tmp=query(1,n).first;
    			ans=min(ans,tmp+vala);
    		}
    	}
    }/*}}}*/
    void build(){
    	sort(a+1,a+1+m);
    	for (int i=1;i<=m;++i){
    		a[i].id=i+n;
    		Lct::b[a[i].id]=a[i].b;
    		Lct::pushup(a[i].id);
    	}
    }
    void solve(){
    	ans=inf;
    	int tmp=0;
    	for (int i=1;i<=m;++i){
    		Lct::Link(a[i].x,a[i].y,a[i].id,a[i].a);
    		//printf("%d
    ",ans);
    	}
    	if (ans!=inf) printf("%d
    ",ans);
    	else printf("-1
    ");
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=m;++i){
    		scanf("%d%d%d%d
    ",&a[i].x,&a[i].y,&a[i].a,&a[i].b);
    	}
    	build();
    	//for (int i=1;i<=m;++i) printf("%d %d %d %d
    ",a[i].x,a[i].y,a[i].a,a[i].b);
    	solve();
    }
    
  • 相关阅读:
    Linux-grep 命令和find 命令 (6)
    第1阶段——u-boot分析之make 100ask24x0_config指令(1)
    shell变量$(CURDIR),$0,$1,$2,$#含义解释
    ln命令详解
    快速解决设置Android 23.0以上版本对SD卡的读写权限无效的问题
    java.io.IOException: Cleartext HTTP traffic to xxx.xxx.xxx.xxx not permitted
    AndroidStudio 3.0中之后无法打开DDMS [Android Device Monitor] 问题
    解决android sdk docs帮助文档打开慢的问题
    Android Intent的使用
    约束布局ConstraintLayout详解
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9471302.html
Copyright © 2011-2022 走看看