zoukankan      html  css  js  c++  java
  • [bzoj3669][Noi2014]魔法森林

    题目大意:有一张$n$个点,$m$条边的无向图,第$i$条边有权值$a_i,b_i$,求一条$1$到$n$的路径,使得这条路径上$max{a_i}+max{b_i}$最小

    题解:先想到二分,然而两个权值,有没有关键字先后顺序的二分我并不会。。。

    然后发现,可以先按$a_i$把每条边排序,一条一条加入。若一条边的端点原来就已经连接,就找到原来路径上$max{b_i}$,把这条边删去,再加上这条新的边。如果这时$1->n$已经连通,就更新答案。$LCT$

    可以用$LCT$来维护路径最大值即可

    卡点:$access$时断重边断错

    C++ Code:

    #include <cstdio>
    #include <algorithm>
    #define maxn 50010
    #define maxm 100010
    #define N maxn + maxm
    #define lc(x) son[x][0]
    #define rc(x) son[x][1]
    const int inf = 0x3f3f3f3f;
    int n, m, ans = inf;
    int fa[N], son[N][2], tg[N], mx[N];
    int w[N];
    inline int get(int rt) {return son[fa[rt]][1] == rt;}
    inline bool isrt(int rt) {return lc(fa[rt]) != rt && rc(fa[rt]) != rt;}
    inline void swap(int &a, int &b) {a ^= b ^= a ^= b;}
    inline void swap(int rt) {swap(lc(rt), rc(rt));};
    inline void pushdown(int rt) {
    	swap(rt), tg[rt] ^= 1;
    	tg[lc(rt)] ^= 1, tg[rc(rt)] ^= 1;
    }
    inline int gmax(int a, int b) {return w[a] > w[b] ? a : b;}
    inline void pushup(int rt) {
    	mx[rt] = rt;
    	if (lc(rt)) mx[rt] = gmax(rt, mx[lc(rt)]);
    	if (rc(rt)) mx[rt] = gmax(mx[rt], mx[rc(rt)]);
    }
    inline void rotate(int x) {
    	int y = fa[x], z = fa[y], b = get(x);
    	if (!isrt(y)) son[z][get(y)] = x;
    	fa[son[y][b] = son[x][!b]] = y; son[x][!b] = y;
    	fa[y] = x; fa[x] = z;
    	pushup(x), pushup(y);
    }
    int S[N], top;
    inline void splay(int x) {
    	S[top = 1] = x;
    	for (int y = x; !isrt(y); S[++top] = y = fa[y]);
    	for (; top; top--) if (tg[S[top]]) pushdown(S[top]);
    	for (; !isrt(x); rotate(x)) if (!isrt(fa[x])) 
    		get(x) ^ get(fa[x]) ? rotate(x) : rotate(fa[x]);
    	pushup(x);
    }
    inline void access(int rt) {for (int t = 0; rt; rc(rt) = t, t = rt, rt = fa[rt]) splay(rt);}
    inline void mkrt(int rt) {access(rt), splay(rt), tg[rt] ^= 1;}
    inline void link(int x, int y) {mkrt(x), fa[x] = y;}
    inline void split(int x, int y) {mkrt(x), access(y), splay(y);}
    inline void cut(int x, int y) {split(x, y), lc(y) = fa[x] = 0;}
    inline int getmax(int x, int y) {split(x, y); return mx[y];}
    inline bool connect(int x, int y) {
    	split(x, y);
    	int now = y;
    	while (lc(now)) now = lc(now);
    	return now == x;
    }
    struct Edge {
    	int u, v, a, b;
    	inline bool operator < (const Edge &rhs) const {return a < rhs.a;}
    } e[maxm];
    inline int min(int a, int b) {return a < b ? a : b;}
    int main() {
    	scanf("%d%d", &n, &m);
    	for (int i = 0; i < m; i++) {
    		scanf("%d%d%d%d", &e[i].u, &e[i].v, &e[i].a, &e[i].b);
    	}
    	std::sort(e, e + m);
    	for (int i = 0; i < m; i++) {
    		int u = e[i].u, v = e[i].v, t = i + n + 1;
    		w[t] = e[i].b;
    		if (!connect(u, v)) link(u, t), link(v, t);
    		else {
    			int pos = getmax(u, v);
    			if (w[pos] > e[i].b) {
    				cut(e[pos - n - 1].u, pos), cut(e[pos - n - 1].v, pos);
    				link(u, t), link(v, t);
    			}
    		}
    		if (connect(1, n)) ans = min(ans, e[i].a + w[getmax(1, n)]);
    	}
    	if (ans == inf) puts("-1");
    	else printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    skywalking简介
    .Net Core微服务——Consul(4):搭建集群
    .Net Core微服务——Consul(3):健康检查
    .Net Core微服务——Consul(2):自动扩展、服务调用
    .Net Core微服务——Consul(1):服务发现
    SpringBoot数据访问之整合Mybatis配置文件
    SpringBoot数据访问之Druid启动器的使用
    SpringBoot数据访问之Druid数据源的自定义使用
    Spring Boot核心技术之Restful映射以及源码的分析
    SpringBoot之yaml语法及静态资源访问
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9580473.html
Copyright © 2011-2022 走看看