BZOJ3669 膜法森林 - LCT
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的更多相关文章
- bzoj3669: [Noi2014]魔法森林 lct版
先上题目 bzoj3669: [Noi2014]魔法森林 这道题首先每一条边都有一个a,b 我们按a从小到大排序 每次将一条路劲入队 当然这道题权在边上 所以我们将边化为点去连接他的两个端点 当然某两 ...
- bzoj3669: [Noi2014]魔法森林 lct
记得去年模拟赛的时候好像YY出二分答案枚举a,b的暴力,过了55欸 然后看正解,为了将两维变成一维,将a排序,模拟Kruskal的加边过程,同时维护1到n的最大值,加入一条边e(u,v,a,b)时有以 ...
- [bzoj3669][Noi2014]魔法森林——lct
Brief description 给定一个无向图,求从1到n的一条路径使得这条路径上最大的a和b最小. Algorithm Design 以下内容选自某HN神犇的blog 双瓶颈的最小生成树的感觉, ...
- [BZOJ3669] [NOI2004] 魔法森林 LCT维护最小生成树
题面 一开始看到这道题虽然知道是跟LCT维护最小生成树相关的但是没有可以的去想. 感觉可以先二分一下总的精灵数,但是感觉不太好做. 又感觉可以只二分一种精灵,用最小生成树算另一种精灵,但是和似乎不单调 ...
- 【OpenJudge3531】【背包DP】【膜法交配律】判断整除
判断整除 总时间限制: 1000ms 内存限制: 65536kB [描述] 一个给定的正整数序列,在每个数之前都插入+号或-号后计算它们的和.比如序列:1.2.4共有8种可能的序列:(+1) + (+ ...
- [luogu3767]膜法
[luogu3767]膜法 luogu 神仙题 线段树分治+带权并查集 把每个操作看成点 首先这个操作的结构是一棵树 你发现每个点的对它的子树产生影响 我们可以想到用dfn序把它转成一段区间用线段树分 ...
- 【BZOJ3669】[Noi2014]魔法森林 LCT
终于不是裸的LCT了...然而一开始一眼看上去这是kruskal..不对,题目要求1->n的路径上的每个点的两个最大权值和最小,这样便可以用LCT来维护一个最小生成路(瞎编的...),先以a为关 ...
- 【BZOJ3669】【NOI2014】魔法森林 LCT
题目描述 给你一个\(n\)个点\(m\)条边的图,每条边有两个边权\(a,b\).请你找出从\(1\)到\(n\)一条路径,使得这条路径上边权\(a\)的最大值\(+\)边权\(b\)的最大值最小. ...
- BZOJ3669[Noi2014]魔法森林——kruskal+LCT
题目描述 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节点1,隐士则住 ...
随机推荐
- 03_java基础(三)之第一个程序与开发工具的安装
1.第一个Java程序 ① 找一个特定的放代码的地方 ② 新建一个文本文档 --> 改名 Hello.java 注意 : 必须先把文件的后缀名都显示出来 不同的操作系 ...
- mysql 模糊搜索
[mysql 模糊搜索] like,%,_,[],[^] 参考:http://www.jb51.net/article/31904.htm
- java方法中增加不固定参数
JDK1.5以上支持 一.定义方法 有时方法的参数个数不固定,可以使用...来省略个数,使用时直接遍历即可,例如下面的方法 public class hi { public void print(St ...
- python生成Excel图表(通过xlsxwriter)
前面介绍了pandas的简单用法,pandas的数据可以通过matlab第三方包将数据生成报表,但是我想将报表生成在Excel中,这时候就可以借助xlsxwriter第三方包来生成图标 缺点:xl ...
- I/O复用之epoll
epoll 简介 epoll是为处理大批量句柄而作了改进的poll,它是在2.5.44内核中被引进的. 相关函数调用 int epoll_create(int size); 创建一个epoll的句柄. ...
- angularjs $watch
参考 https://blog.csdn.net/u010451286/article/details/50635839 scope.$watch("field1 + field2" ...
- H5 边框:带border的百分比布局
响应式Web设计经常需要我们通过百分比设置组件宽度.如果我们不考虑边框,那么很容易就可以实现,但如果你给每一列以及总宽度都采用百分比设置,那这个时候固定的边框大小就会出来捣乱.下面我们将看到一组方法去 ...
- 第二章 向量(e)起泡排序
- CentOS 查看进程状态
Linux中ps与top命令 ============================================================================ 这两个命令都 ...
- Android 性能测试之CPU
接上一篇 CPU跟内存一样,存在一些测试子项,如下清单所示 1.空闲状态下的应用CPU消耗情况 2.中等规格状态下的应用CPU消耗情况 3.满规格状态下的应用CPU消耗情况 4.应用CPU峰值情况 C ...