zoukankan      html  css  js  c++  java
  • luogu2387 [NOI2014]魔法森林

    这题和水管局长很像,枚举 (a) 的边然后维护关于 (b) 的最小生成树就可以了。
    1A呐>_<

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    using namespace std;
    int n, m, val[150005], zdz[150005], ans=0x3f3f3f3f, fa[150005];
    int ch[150005][2], rev[150005];
    struct Edge{
    	int fro, too, vaa, vab;
    }edge[100005];
    bool cmp(Edge x, Edge y){
    	return x.vaa<y.vaa;
    }
    void upd(int x){
    	zdz[x] = val[x];
    	if(edge[zdz[ch[x][0]]].vab>edge[zdz[x]].vab)
    		zdz[x] = zdz[ch[x][0]];
    	if(edge[zdz[ch[x][1]]].vab>edge[zdz[x]].vab)
    		zdz[x] = zdz[ch[x][1]];
    }
    int getw(int x){
    	return ch[fa[x]][1]==x;
    }
    bool isroot(int x){
    	return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
    }
    void pushdown(int x){
    	if(rev[x]){
    		swap(ch[x][0], ch[x][1]);
    		rev[ch[x][0]] ^= 1;
    		rev[ch[x][1]] ^= 1;
    		rev[x] = false;
    	}
    }
    void xf(int x){
    	if(fa[x])	xf(fa[x]);
    	pushdown(x);
    }
    void rotate(int x){
    	int old=fa[x], oldf=fa[old], w=getw(x);
    	if(!isroot(old))	ch[oldf][ch[oldf][1]==old] = x;
    	ch[old][w] = ch[x][w^1]; ch[x][w^1] = old;
    	fa[ch[old][w]] = old; fa[ch[x][w^1]] = x; fa[x] = oldf;
    	upd(old); upd(x);
    }
    void splay(int x){
    	xf(x);
    	while(!isroot(x)){
    		int f=fa[x];
    		if(!isroot(f))	rotate(getw(f)==getw(x)?f:x);
    		rotate(x);
    	}
    	upd(x);
    }
    void access(int x){
    	int y=0;
    	while(x){
    		splay(x);
    		ch[x][1] = y;
    		upd(x);
    		y = x;
    		x = fa[x];
    	}
    }
    void makeroot(int x){
    	access(x);
    	splay(x);
    	rev[x] ^= 1;
    }
    int findroot(int x){
    	access(x);
    	splay(x);
    	while(ch[x][0])
    		x = ch[x][0];
    	splay(x);
    	return x;
    }
    void split(int x, int y){
    	makeroot(x);
    	access(y);
    	splay(y);
    }
    void link(int x, int y){
    	makeroot(x);
    	fa[x] = y;
    }
    void cut(int x, int y){
    	split(x, y);
    	fa[x] = ch[y][0] = 0;
    }
    int main(){
    	cin>>n>>m;
    	for(int i=1; i<=m; i++){
    		scanf("%d %d %d %d", &edge[i].fro, &edge[i].too, &edge[i].vaa, &edge[i].vab);
    		if(edge[i].fro>edge[i].too)    swap(edge[i].fro, edge[i].too);
    	}
    	for(int i=n+1; i<=n+m; i++)
    		val[i] = zdz[i] = i - n;
    	sort(edge+1, edge+1+m, cmp);
    	int j=1;
    	for(int i=1; i<=50000; i++){
    		for(; j<=m && edge[j].vaa<=i; j++){
    			int x=edge[j].fro, y=edge[j].too;
    			if(findroot(x)!=findroot(y)){
    				link(x, j+n);
    				link(y, j+n);
    			}
    			else{
    				split(x, y);
    				int idx=zdz[y];
    				if(edge[j].vab<edge[idx].vab){
    					cut(edge[idx].fro, idx+n);
    					cut(edge[idx].too, idx+n);
    					link(edge[j].fro, j+n);
    					link(edge[j].too, j+n);
    				}
    			}
    		}
    		if(findroot(1)==findroot(n)){
    			split(1, n);
    			ans = min(ans, i+edge[zdz[n]].vab);
    		}
    	}
    	if(ans!=0x3f3f3f3f)	printf("%d
    ", ans);
    	else	printf("%d
    ", -1);
    	return 0;
    }
    
  • 相关阅读:
    《Code Complete》ch.18 表驱动法
    libevent I/O示例
    Unity3d 与 Objective-C 数据交互,持续更新中
    progress 相关事件 异步 ajax
    数据结构chapter01_C++基础
    vue环境搭建
    时间复杂度和空间复杂度
    linux内核数据结构之链表
    linux内核数据结构之kfifo
    c++ iterator(迭代器)分类及其使用
  • 原文地址:https://www.cnblogs.com/poorpool/p/9114726.html
Copyright © 2011-2022 走看看