[BZOJ 3669] [Noi2014] 魔法森林 【LCT】
题目链接:BZOJ - 3669
题目分析
如果确定了带 x 只精灵A,那么我们就是要找一条 1 到 n 的路径,满足只经过 Ai <= x 的边,而且要使经过的边中最大的 Bi 尽量小。
其实就是一个按照 Bi 建立的 MST 上 1 到 n 的路径。只能使用 Ai <= x 的边。
那么,如果我们从小到大枚举 x ,这样可以使用的边就不断增加,就是在加边的同时维护 MST ,用 LCT 来做就可以了。
如果新加入一条边 (u, v, w) ,并且原 MST 上 u 到 v 的路径中边权最大的边的边权大于 w ,那么就删掉那条边权最大的边,然后把这条新加入的边连到 MST 中。
备注:在 Cut 不够优的边时,我之前将代码写出了非常可怕的 BUG ,但是由于神奇的写法的巧合,这个 BUG 并没有造成后果,我用错误的代码 AC 了两道题..
现在下方的代码是正确的了。
代码
- #include <iostream>
- #include <cstdlib>
- #include <cstring>
- #include <cstdio>
- #include <cmath>
- #include <algorithm>
- using namespace std;
- inline void Read(int &Num)
- {
- char c = getchar();
- while (c < '0' || c > '9') c = getchar();
- Num = c - '0'; c = getchar();
- while (c >= '0' && c <= '9')
- {
- Num = Num * 10 + c - '0';
- c = getchar();
- }
- }
- inline int gmax(int a, int b) {return a > b ? a : b;}
- inline int gmin(int a, int b) {return a < b ? a : b;}
- const int MaxN = 50000 + 5, MaxM = 100000 + 5, MaxT = 150000 + 5, INF = 999999999;
- int n, m, Ans;
- int Father[MaxT], Son[MaxT][2], V[MaxT], T[MaxT];
- bool isRoot[MaxT], Rev[MaxT];
- struct ES
- {
- int u, v, p, q;
- } E[MaxM];
- inline bool Cmp(ES e1, ES e2)
- {
- return e1.p < e2.p;
- }
- /**************************** LCT Start *******************************/
- inline int Tmax(int a, int b) {return V[a] > V[b] ? a : b;}
- inline void Update(int x)
- {
- T[x] = Tmax(x, Tmax(T[Son[x][0]], T[Son[x][1]]));
- }
- inline void Reverse(int x)
- {
- Rev[x] = !Rev[x];
- swap(Son[x][0], Son[x][1]);
- }
- inline void PushDown(int x)
- {
- if (!Rev[x]) return;
- Rev[x] = false;
- if (Son[x][0]) Reverse(Son[x][0]);
- if (Son[x][1]) Reverse(Son[x][1]);
- }
- inline int GetDir(int x)
- {
- if (x == Son[Father[x]][0]) return 0;
- else return 1;
- }
- void Rotate(int x)
- {
- int y = Father[x], f;
- PushDown(y); PushDown(x);
- f = GetDir(x) ^ 1;
- if (isRoot[y])
- {
- isRoot[y] = false;
- isRoot[x] = true;
- }
- else
- {
- if (y == Son[Father[y]][0]) Son[Father[y]][0] = x;
- else Son[Father[y]][1] = x;
- }
- Father[x] = Father[y];
- Son[y][f ^ 1] = Son[x][f];
- if (Son[x][f]) Father[Son[x][f]] = y;
- Son[x][f] = y;
- Father[y] = x;
- Update(y); Update(x);
- }
- void Splay(int x)
- {
- int y;
- while (!isRoot[x])
- {
- y = Father[x];
- if (isRoot[y])
- {
- Rotate(x);
- break;
- }
- if (GetDir(y) == GetDir(x)) Rotate(y);
- else Rotate(x);
- Rotate(x);
- }
- }
- int Access(int x)
- {
- int y = 0;
- while (x != 0)
- {
- Splay(x);
- PushDown(x);
- if (Son[x][1]) isRoot[Son[x][1]] = true;
- Son[x][1] = y;
- if (y) isRoot[y] = false;
- Update(x);
- y = x;
- x = Father[x];
- }
- return y;
- }
- inline void Make_Root(int x)
- {
- int t = Access(x);
- Reverse(t);
- }
- inline void Link(int x, int y)
- {
- Make_Root(x);
- Splay(x);
- Father[x] = y;
- }
- inline void Cut(int x, int y)
- {
- Make_Root(x);
- Access(y);
- Splay(y);
- PushDown(y);
- isRoot[Son[y][0]] = true;
- Father[Son[y][0]] = 0;
- Son[y][0] = 0;
- Update(y);
- }
- inline int Find_Root(int x)
- {
- int t = Access(x);
- while (Son[t][0] != 0) t = Son[t][0];
- return t;
- }
- /**************************** LCT End *******************************/
- int main()
- {
- scanf("%d%d", &n, &m);
- for (int i = 1; i <= m; ++i)
- {
- Read(E[i].u); Read(E[i].v);
- Read(E[i].p); Read(E[i].q);
- }
- sort(E + 1, E + m + 1, Cmp); // by ES.p
- for (int i = 1; i <= m; ++i) V[n + i] = E[i].q;
- for (int i = 1; i <= n + m; ++i)
- {
- isRoot[i] = true;
- Father[i] = 0;
- T[i] = i;
- }
- Ans = INF;
- int t, CutE;
- for (int i = 1; i <= m; ++i)
- {
- if (Find_Root(E[i].u) != Find_Root(E[i].v))
- {
- Link(E[i].u, n + i); Link(E[i].v, n + i);
- }
- else
- {
- Make_Root(E[i].u);
- t = Access(E[i].v);
- if (V[T[t]] > E[i].q)
- {
- CutE = T[t];
- Cut(CutE, E[CutE - n].u); Cut(CutE, E[CutE - n].v);
- Link(E[i].u, n + i); Link(E[i].v, n + i);
- }
- }
- if (Find_Root(1) == Find_Root(n))
- {
- Make_Root(1);
- t = Access(n);
- Ans = gmin(Ans, E[i].p + V[T[t]]);
- }
- }
- if (Ans == INF) Ans = -1;
- printf("%d\n", Ans);
- return 0;
- }
[BZOJ 3669] [Noi2014] 魔法森林 【LCT】的更多相关文章
- BZOJ 3669: [Noi2014]魔法森林( LCT )
排序搞掉一维, 然后就用LCT维护加边MST. O(NlogN) ------------------------------------------------------------------- ...
- bzoj 3669: [Noi2014]魔法森林 (LCT)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3669 题面: 3669: [Noi2014]魔法森林 Time Limit: 30 Sec ...
- bzoj 3669: [Noi2014] 魔法森林 LCT版
Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...
- BZOJ 3669: [Noi2014]魔法森林 [LCT Kruskal | SPFA]
题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...
- BZOJ 3669: [Noi2014]魔法森林(lct+最小生成树)
传送门 解题思路 \(lct\)维护最小生成树.我们首先按照\(a\)排序,然后每次加入一条边,在图中维护一棵最小生成树.用并查集判断一下\(1\)与\(n\)是否联通,如果联通的话就尝试更新答案. ...
- bzoj 3669: [Noi2014]魔法森林
bzoj 3669: [Noi2014]魔法森林 Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号 ...
- bzoj 3669: [Noi2014]魔法森林 动态树
3669: [Noi2014]魔法森林 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 363 Solved: 202[Submit][Status] ...
- bzoj 3669: [Noi2014]魔法森林 -- 动点spfa
3669: [Noi2014]魔法森林 Time Limit: 30 Sec Memory Limit: 512 MB 动点spfa Description 为了得到书法大家的真传,小E同学下定决心 ...
- bzoj 3669: [Noi2014]魔法森林(并查集+LCT)
Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...
随机推荐
- 【Qt】测测你对Qt的了解–Qt工具知多少
原文:http://blog.163.com/lijiji_1515/blog/static/1268774462009103101944455/ 你知道Qt都提供了哪些工具吗? 你知道Qt的 ...
- 编写跨平台代码之memory alignment
编写网络包(存储在堆上)转换程序时,在hp-ux机器上运行时会遇到 si_code: 1 - BUS_ADRALN - Invalid address alignment. Please refer ...
- ClassLoader(摘录)
Java虚拟机类加载过程是把Class类文件加载到内存,并对Class文件中的数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型的过程. 在加载阶段,java虚拟机需要完成以下 ...
- JavaScript小笔记の经典算法等....
1.利用toString()里面的参数,实现各进制之间的快速转换: var n = 17; binary_string = n.toString(2); //->二进制"10001&q ...
- display: inline-block 的神奇效果
先上要实现的效果图: 方案一:来自卢兄: <!DOCTYPE html> <html lang="en"> <head> <meta ch ...
- .NET设计模式(10):装饰模式(Decorator Pattern)
.NET设计模式(10):装饰模式(Decorator Pattern) 装饰模式(Decorator Pattern) --.NET设计模式系列之十 年月..在....对于..由于使用装饰模 ...
- T-SQL中的透视和逆透视
透视 今天抽一点时间来看看透视和逆透视语句,简单的说就是行列转换.假设一个销售表中存放着产品号,产品折扣,产品价格三个列,每一种产品号可能有多种折扣,每一种折扣只对应一个产品价格.下面贴出建表语句和插 ...
- pat_1009
1009. 说反话 (20) 时间限制 400 ms 内存限制 32000 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 给定一句英语,要求你编写程序,将句中 ...
- Node之express
Express 是一个简洁.灵活的 node.js Web 应用开发框架, 它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用. 如何安装: npm install -g express ...
- ZOJ 1234 Chopsticks(动态规划)
Chopsticks 题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=234 题目大意:给定n个筷子的长度,取k+8套筷 ...