Solution

非常妙的排序啊。。。

仔细想想好像确实能够找出最优解QUQ

先对第一关键字排序, 在$LCT$ 维护第二关键字的最大值 所在的边。

添边时如果$u, v$ 不连通 就直接加边。  如果连通 并且路径上的最大值 大于 当前边 的 第二关键字, 那么可以换掉。

如果 $1$ 和 $N$ 连通 就 更新答案。

这样就可以保证 在 所有路径上的边 第一关键字 小于等于 当前边 的第一关键字的前提下, 第二关键字的 最大值  最小。

除了这一点不一样, 其他就是模板了。

Code

 #include<cstdio>
#include<cstring>
#include<algorithm>
#define rd read()
using namespace std; const int N = 1e5 + ;
const int inf = ~0U >> ; int n, m;
int ans = inf; struct edge {
int u, v, a, b;
}e[N << ]; int read() {
int X = , p = ; char c = getchar();
for (; c > '' || c < ''; c = getchar())
if (c == '-') p = -;
for (; c >= '' && c <= ''; c = getchar())
X = X * + c - '';
return X * p;
} int cmp(const edge &A, const edge &B) {
return A.a < B.a;
} void cmin(int &A, int B) {
if (A > B)
A = B;
} namespace LCT {
int val[N << ], f[N << ], ch[N << ][], mx[N << ], tun[N << ];
#define lc(x) ch[x][0]
#define rc(x) ch[x][1] int isroot(int x) {
return lc(f[x]) != x && rc(f[x]) != x;
} int get(int x) {
return rc(f[x]) == x;
} void up(int x) {
mx[x] = val[x];
if (e[mx[lc(x)]].b > e[mx[x]].b) mx[x] = mx[lc(x)];
if (e[mx[rc(x)]].b > e[mx[x]].b) mx[x] = mx[rc(x)];
} void rev(int x) {
swap(lc(x), rc(x));
tun[x] ^= ;
} void pushdown(int x) {
if (tun[x]) {
if (lc(x)) rev(lc(x));
if (rc(x)) rev(rc(x));
tun[x] = ;
}
} int st[N << ], tp; void pd(int x) {
while (!isroot(x)) {
st[++tp] = x;
x = f[x];
}
pushdown(x);
while (tp) pushdown(st[tp--]);
} void rotate(int x) {
int old = f[x], oldf = f[old], son = ch[x][get(x) ^ ];
if (!isroot(old)) ch[oldf][get(old)] = x;
ch[x][get(x) ^ ] = old;
ch[old][get(x)] = son;
f[old] = x; f[son] = old; f[x] = oldf;
up(old); up(x);
} void splay(int x) {
pd(x);
for (; !isroot(x); rotate(x))
if (!isroot(f[x]))
rotate(get(f[x]) == get(x) ? f[x] : x);
} void access(int x) {
for (int y = ; x; y = x, x = f[x])
splay(x), ch[x][] = y, up(x);
} void mroot(int x) {
access(x); splay(x); rev(x);
} void split(int x, int y) {
mroot(x); access(y); splay(y);
} int findr(int x) {
access(x); splay(x);
while(lc(x)) pushdown(x), x = lc(x);
return x;
} void link(int x, int y) {
mroot(x); f[x] = y;
} void cut(int x, int y) {
split(x, y);
f[x] = ch[y][] = ;
}
}
using namespace LCT; int main()
{
n = rd; m = rd;
for (int i = ; i <= m; ++i) {
e[i].u = rd; e[i].v = rd;
e[i].a = rd; e[i].b = rd;
}
sort(e + , e + + m, cmp);
for (int i = ; i <= m; ++i)
val[i + n] = i;
for (int i = ; i <= m; ++i) {
int x = e[i].u, y = e[i].v, t;
if (x == y) continue;
mroot(x);
if (findr(y) != x)
link(i + n, x), link(i + n, y);
else if (e[t = mx[y]].b > e[i].b)
cut(t + n, e[t].u), cut(t + n, e[t].v),
link(i + n, x), link(i + n, y);
mroot();
if (findr(n) == )
cmin(ans, e[i].a + e[mx[n]].b);
}
printf("%d\n", ans == inf ? - : ans);
}

BZOJ3669 膜法森林 - LCT的更多相关文章

  1. bzoj3669: [Noi2014]魔法森林 lct版

    先上题目 bzoj3669: [Noi2014]魔法森林 这道题首先每一条边都有一个a,b 我们按a从小到大排序 每次将一条路劲入队 当然这道题权在边上 所以我们将边化为点去连接他的两个端点 当然某两 ...

  2. bzoj3669: [Noi2014]魔法森林 lct

    记得去年模拟赛的时候好像YY出二分答案枚举a,b的暴力,过了55欸 然后看正解,为了将两维变成一维,将a排序,模拟Kruskal的加边过程,同时维护1到n的最大值,加入一条边e(u,v,a,b)时有以 ...

  3. [bzoj3669][Noi2014]魔法森林——lct

    Brief description 给定一个无向图,求从1到n的一条路径使得这条路径上最大的a和b最小. Algorithm Design 以下内容选自某HN神犇的blog 双瓶颈的最小生成树的感觉, ...

  4. [BZOJ3669] [NOI2004] 魔法森林 LCT维护最小生成树

    题面 一开始看到这道题虽然知道是跟LCT维护最小生成树相关的但是没有可以的去想. 感觉可以先二分一下总的精灵数,但是感觉不太好做. 又感觉可以只二分一种精灵,用最小生成树算另一种精灵,但是和似乎不单调 ...

  5. 【OpenJudge3531】【背包DP】【膜法交配律】判断整除

    判断整除 总时间限制: 1000ms 内存限制: 65536kB [描述] 一个给定的正整数序列,在每个数之前都插入+号或-号后计算它们的和.比如序列:1.2.4共有8种可能的序列:(+1) + (+ ...

  6. [luogu3767]膜法

    [luogu3767]膜法 luogu 神仙题 线段树分治+带权并查集 把每个操作看成点 首先这个操作的结构是一棵树 你发现每个点的对它的子树产生影响 我们可以想到用dfn序把它转成一段区间用线段树分 ...

  7. 【BZOJ3669】[Noi2014]魔法森林 LCT

    终于不是裸的LCT了...然而一开始一眼看上去这是kruskal..不对,题目要求1->n的路径上的每个点的两个最大权值和最小,这样便可以用LCT来维护一个最小生成路(瞎编的...),先以a为关 ...

  8. 【BZOJ3669】【NOI2014】魔法森林 LCT

    题目描述 给你一个\(n\)个点\(m\)条边的图,每条边有两个边权\(a,b\).请你找出从\(1\)到\(n\)一条路径,使得这条路径上边权\(a\)的最大值\(+\)边权\(b\)的最大值最小. ...

  9. BZOJ3669[Noi2014]魔法森林——kruskal+LCT

    题目描述 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节点1,隐士则住 ...

随机推荐

  1. hdu2973-YAPTCHA-(欧拉筛+威尔逊定理+前缀和)

    YAPTCHA Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  2. c3 新特性

    渐变 线性渐变 .line {     height: 100px;     /*线性渐变语法*/     background-image: linear-gradient( to right,/* ...

  3. SQL server 2012完全删除

    第一步,在控制面板里面找到程序——卸载程序这一项,打开之后就会是这样的了 第二步,经过第一步打开卸载程序后,在里面找到Microsoft SQLserver 2012 (64-bit)这一项,可以通过 ...

  4. Alpine Linux 使用简介

    https://blog.csdn.net/csdn_duomaomao/article/details/76152416

  5. vue 中下拉select怎样给后台传递用户选择的物品id

    在泰康保险公众号项目中有个问题是用户选择select中的option,要把对应的id给后台以便后台工作作出相应的效果,我是这样的 <select v-model="selectcomu ...

  6. 设置,获取,删除cookie

    function setCookie(key,value,options){ if (value !== undefined ) { if(options === undefined || optio ...

  7. 解题7(FindFirstOnlyOne)

    题目描述 找出字符串中第一个只出现一次的字符 输入描述: 输入一个非空字符串 输出描述: 输出第一个只出现一次的字符,如果不存在输出-1 示例1 输入 asdfasdfo 输出 o 代码如下: pac ...

  8. python return 及lambda函数

    return有两个作用: 1.用来返回函数的运行结果,或者调用另外一个函数.比如max()函数 >>> def fun(a,b): #返回函数结果. return max(a,b) ...

  9. sqlserver 查看当前连接数

    参考 https://www.cnblogs.com/lumnm/archive/2009/08/29/1556349.html SELECT * FROM[Master].[dbo].[SYSPRO ...

  10. SQLdeveloper换成windows主题后不显示的情况

    这几天因为换电脑需要重新安装数据库, 因为换成了64位系统, 原先的oracle数据库也换成了64位, 但是plsql还是要用32位的, 经过深思熟虑也没装, 请教了一个同学改用oracle自带的sq ...