解析

LCT从板子到算法的入门题吧
有一些不知道的很实用的技巧

把边按a排序从小到大加入边
那么我们只需要维护当前1-n路径上的b的最小值即可
如果这条边两端点本来不连通,就直接link
否则找到路径上b最大的一条边,断掉,再加入当前边(前提是b最大的边的b大于当前边)

实现上,可以把每条边转化成一个虚点
十分方便

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e5+100;
const int mod=1e9+7;
const double eps=1e-9;
inline ll read() {ll x(0),f(1);char c=getchar();while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}int n,m;#define ls(o) tr[o][0]
#define rs(o) tr[o][1]
int tr[N][2],f[N],rev[N],val[N],mx[N];
inline bool isroot(int x) {return tr[f[x]][0]!=x&&tr[f[x]][1]!=x;
}
inline bool which(int x) {return tr[f[x]][1]==x;
}
inline void pushup(int x) {if(x){mx[x]=x;if(ls(x)&&val[mx[ls(x)]]>val[mx[x]]) mx[x]=mx[ls(x)];if(rs(x)&&val[mx[rs(x)]]>val[mx[x]]) mx[x]=mx[rs(x)];}return;
}
inline void tag(int x) {if(x) {rev[x]^=1;swap(tr[x][0],tr[x][1]);}
}
inline void pushdown(int x) {if(rev[x]){rev[x]=0;tag(tr[x][0]);tag(tr[x][1]);}return;
}
void debug(int x) {if(!x) return;pushdown(x);debug(tr[x][0]);printf("debug: x=%d ls=%d rs=%d\n",x,tr[x][0],tr[x][1]);debug(tr[x][1]);return;
}
inline void rotate(int x) {int fa=f[x],gfa=f[fa];int d=which(x),son=tr[x][d^1];f[x]=gfa;if(!isroot(fa)) tr[gfa][which(fa)]=x;f[fa]=x;tr[x][d^1]=fa;if(son){f[son]=fa;}tr[fa][d]=son;pushup(fa);pushup(x);return;
}
int zhan[N];
inline void splay(int x) {int y=x,top=0;zhan[++top]=y;while(!isroot(y)) zhan[++top]=y=f[y];while(top) pushdown(zhan[top--]);for(int fa; fa=f[x],!isroot(x); rotate(x)) {if(!isroot(fa)) which(fa)==which(x)?rotate(fa):rotate(x);}return;
}
inline void access(int x) {for(int y(0); x; y=x,x=f[x]) {splay(x);tr[x][1]=y;pushup(x);if(y) f[y]=x;}return;
}
inline void makeroot(int x) {access(x);splay(x);tag(x);return;
}
inline int findroot(int x) {access(x);splay(x);while(pushdown(x),tr[x][0]) x=tr[x][0];splay(x);return x;
}
inline void link(int x,int y) {makeroot(x);if(findroot(y)==x) return;f[x]=y;pushup(y);//printf("link: %d -> %d\n",x,y);
}
inline void cut(int x,int y) {makeroot(x);access(y);splay(y);if(tr[y][0]!=x||tr[x][1]) return;tr[y][0]=f[x]=0;pushup(y);return;
}
inline void split(int x,int y){//y is fathermakeroot(x);access(y);splay(y);return;
}
struct edge{int x,y,a,b;bool operator < (const edge oth)const{return a<oth.a;}
}e[N];
int main() {#ifndef ONLINE_JUDGE//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);
#endifn=read();m=read();for(int i=1;i<=m;i++) e[i]=(edge){(int)read(),(int)read(),(int)read(),(int)read()};sort(e+1,e+1+m);int ans(2e9);for(int i=1;i<=m;i++){int x=e[i].x,y=e[i].y,w=e[i].b;val[i+n]=w;//printf("\nid=%d (%d %d) w=%d (a=%d)\n",i+n,x,y,w,e[i].a);if(findroot(x)!=findroot(y)) link(x,n+i),link(y,n+i);else{split(x,y);int now=mx[y];if(val[now]>w){splay(now);f[tr[now][0]]=0;tr[now][0]=0;f[tr[now][1]]=0;tr[now][1]=0;pushup(now);link(n+i,x);link(n+i,y);}}if(findroot(1)==findroot(n)){split(1,n);ans=min(ans,val[mx[n]]+e[i].a);//debug(n);}}printf("%d\n",ans<2e9?ans:-1);return 0;
}

YBTOJ洛谷P2387: 魔法森林(LCT)相关推荐

  1. BZOJ 3669: [Noi2014]魔法森林( LCT )

    排序搞掉一维, 然后就用LCT维护加边MST. O(NlogN) ------------------------------------------------------------------- ...

  2. loj2245 [NOI2014]魔法森林 LCT

    [NOI2014]魔法森林 链接 loj 思路 a排序,b做动态最小生成树. 把边拆成点就可以了. uoj98.也许lct复杂度写假了..越卡常,越慢 代码 #include <bits/std ...

  3. YBTOJ洛谷P4074:糖果公园(树上莫队)

    文章目录 解析 update: 代码 所谓树上莫队,就是在树上的莫队 (逃) 传送门 解析 似乎就是树上的这道题 考虑如何转化为序列问题呢? 考虑dfs序 但是又一个问题... 似乎这条链的dfs序不 ...

  4. YBTOJ洛谷P4551:最长异或路径(trie树)

    洛谷传送门 文章目录 题目描述 解析 代码 题目描述 解析 本题关键就在于一点: 若把每个点的深度dep[i]定义为从根到节点边权的异或和 那么i到j的路径异或和可以表示为: dep[i] ^ dep ...

  5. [BZOJ]3669: [Noi2014]魔法森林 lct

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

  6. 洛谷 p2387 [noi2014] 膜fa♂森林 lct维护最小生成树

    题目简述 做法 题目简述 求1-n的一条路径,路径上所有边的a的最大值和b的最大值相加最小. 做法 首先把边按照 a a a的大小排序,接下来用link_cut_tree维护1→n" rol ...

  7. [Luogu P2387] [NOI2014]魔法森林 (LCT维护边权)

    题面 传送门:https://www.luogu.org/problemnew/show/P2387 Solution 这题的思想挺好的. 对于这种最大值最小类的问题,很自然的可以想到二分答案.很不幸 ...

  8. [P2387魔法森林

    题面 题意: 给出一个图,边权有两维,a与b. 求1到n的一条路径使得路径经过的边的最大的a与b的和最小,输出最小之和. \(Solution:\) 如果做过这题,那么就显得很简单了很好想了. 又是想 ...

  9. 洛谷 P3302 [SDOI2013]森林 主席树+启发式合并

    click here~:https://www.luogu.org/problem/P3302 emmm这个题是真的烦 一看题发现这题不是count on a tree的升级版么 如果一点思路没有的话 ...

最新文章

  1. Django模型层Meta内部类详解
  2. The Ultimate Guide To iPhone Resolutions
  3. (一)神经网络入门之线性回归
  4. boost::geometry模块多边形叠加示例
  5. BZOJ 1604 [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居:队列 + multiset + 并查集【曼哈顿距离变形】...
  6. ios git解决冲突_适用于iOS和Linux的远程同步解决方案:Git和工作副本
  7. 华为云平台创建产品+注册设备
  8. FreeBSD重新加载rc.conf
  9. 杉德支付php代码实现_php实现微信支付的代码
  10. HDU 2552 A simple problem
  11. linux中id命令的功能,Linux id命令参数及用法详解
  12. 【转】MongoDB:C#应用
  13. Symantec Backup Exec 2012修改显示语言
  14. java lambda排序
  15. SPF(最短路径树)算法
  16. 计算机制图孔中心线,机械制图中各种中心线绘制方法.docx
  17. 海思开发:yolo v5s :pytorch->onnx->caffe->nnie
  18. 计算机服务器排名2015,服务器cpu排行榜
  19. 【贪心算法】-背包问题
  20. java 绝对路径双斜线_路径分隔符:正斜线/、反斜线\、双反斜线\\的区别

热门文章

  1. Mysql修改字段名和长度_mysql中修改表字段名/字段长度/字段类型详解
  2. 不确定规划及应用代码_性能测试划分之应用领域
  3. 用wamper打开php源码_php源码该怎么设置数据库
  4. matlab自带kpca,求对矩阵进行PCA或者KPCA特征提取的matlab代码
  5. linux下安装服务,linux下的软件服务安装管理
  6. kafka偏移量保存到mysql里_Kafka 新版消费者 API(二):提交偏移量
  7. io流图解 java_详细讲解JAVA中的IO流
  8. 行者运行脚本命令_行者脚本指令说明
  9. java实用教程——常用实用类——String类(字符串类)
  10. 算法设计与分析———动态规划———最大子段和