Vijos1865 NOI2014 魔法森林 LCT维护生成树
基本思路:
首先按照weightA升序排序,然后依次在图中加边,并维护起点到终点路径上weightB的最大值
如果加边过程中生成了环,则删除环中weightB最大的边
由于是无向图,点之间没有拓扑序,所以在建立LCT模型时,可以将原图的边也视为点,这样就转化成了维护路径上的点权最大值(Orz Hzwer)
点的连通性可以用并查集维护
AC code:(其实Splay双旋一次时只需要进行3次update,而代码中舍弃了这个优化)
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- ;
- ;
- const int inf=0x3f3f3f3f;
- struct Edge
- {
- int u,v;
- int weightA,weightB;
- void assign(int _u,int _v,int _wa,int _wb)
- {
- u=_u; v=_v; weightA=_wa; weightB=_wb;
- }
- bool operator < (const Edge& other) const
- {
- return this->weightA < other.weightA;
- }
- };
- Edge elist[maxM];
- inline int getMaxIdx(int u,int v)
- {
- return elist[u].weightB > elist[v].weightB ? u : v;
- } //Let elist[0].weightB = -inf
- struct Splay
- {
- int idx;
- int maxIdx;
- bool rev;
- Splay* child[];
- Splay* parent;
- void init(int id)
- {
- idx=maxIdx=id;
- rev=false;
- child[]=child[]=parent=;
- }
- bool isRoot()
- {
- if(!parent) return true;
- ] && ];
- }
- void update()
- {
- maxIdx=idx;
- ]) maxIdx=getMaxIdx(]->maxIdx);
- ]) maxIdx=getMaxIdx(]->maxIdx);
- }
- void reverse()
- {
- if(!isRoot()) parent->reverse();
- if(rev) {
- std::swap(child[],child[]);
- ]) child[]->rev ^= ;
- ]) child[]->rev ^= ;
- ;
- }
- }
- ; }
- void rotate(int dir)
- {
- Splay* temp=parent;
- this->parent=temp->parent;
- if(parent)
- {
- ]) parent->child[]=this;
- ]) parent->child[]=this;
- }
- temp->child[dir^]=this->child[dir];
- if(child[dir]) child[dir]->parent=temp;
- child[dir]=temp;
- temp->parent=this;
- temp->update();
- this->update();
- }
- void splay()
- {
- reverse();
- while(!isRoot())
- {
- );
- ]) st|=;
- ;
- if(!parent->isRoot())
- {
- ]) st|=;
- ;
- }
- switch(st)
- {
- : rotate(); break;
- : rotate(); break;
- : parent->rotate(); ); break;
- : rotate(); rotate(); break;
- : rotate(); rotate(); break;
- :parent->rotate(); ); break;
- }
- }
- }
- };
- Splay node[maxN+maxM];
- int access(int idx)
- {
- Splay *cur,*last;
- ;cur;last=cur,cur=cur->parent)
- {
- cur->splay();
- cur->child[]=last;
- cur->update();
- }
- return last->maxIdx;
- }
- inline void setAsRoot(int idx)
- {
- access(idx);
- node[idx].splay();
- node[idx].setRev();
- }
- inline void link(int u,int v)
- {
- setAsRoot(u);
- node[u].parent=node+v;
- }
- inline void cut(int u,int v)
- {
- setAsRoot(u);
- access(v);
- node[v].splay();
- node[v].child[]=node[u].parent=;
- node[v].update();
- }
- inline int query(int u,int v)
- {
- setAsRoot(u);
- return access(v);
- }
- int N,M;
- int center[maxN];
- int getCenter(int idx)
- {
- return center[idx]==idx ? idx :
- center[idx]=getCenter(center[idx]);
- }
- void input()
- {
- scanf("%d%d",&N,&M);
- int u,v,wa,wb;
- ;i<=M;i++)
- {
- scanf("%d%d%d%d",&u,&v,&wa,&wb);
- if(u==v) { --i; --M; }
- else elist[i].assign(u,v,wa,wb);
- }
- }
- void init()
- {
- elist[].weightB=-inf;
- std::sort(elist+,elist+M+);
- ;i<=M;i++) node[i].init(i);
- ;i<=N;i++) node[i+M].init();
- ;i<=N;i++) center[i]=i;
- }
- void addEdge(int e)
- {
- int& u=elist[e].u;
- int& v=elist[e].v;
- int cu=getCenter(u);
- int cv=getCenter(v);
- if(cu!=cv)
- {
- link(e,M+u);
- link(e,M+v);
- center[cu]=cv;
- }
- else {
- int mx=query(M+u,M+v);
- if(elist[e].weightB < elist[mx].weightB)
- {
- cut(mx,M+elist[mx].u);
- cut(mx,M+elist[mx].v);
- link(e,M+u);
- link(e,M+v);
- }
- }
- }
- int solve()
- {
- int ans(inf);
- init();
- ;i<=M;i++)
- {
- addEdge(i);
- )==getCenter(N))
- {
- ,M+N);
- ans=std::min(ans,elist[i].weightA+elist[mx].weightB);
- }
- }
- :ans;
- }
- int main()
- {
- input();
- printf("%d\n",solve());
- ;
- }
——————分割线——————
这道题我Debug了2天共计5h,最后偶然间查明了死因居然是——
- #ifdef WRONG_SPLAY_CODE
- void Splay::splay()
- {
- reverse();
- while(!isRoot())
- {
- );
- ]) st|=;
- ;
- if(!parent->isRoot())
- {
- ]) st|=;
- ;
- }
- switch(st)
- {
- : rotate(); break;
- : rotate(); break;
- : parent->rotate(); ); break;
- : rotate(); rotate(); break;
- : rotate(); rotate(); break;
- :parent->rotate(); ); break;
- }
- }
- }
- #endif
I FELL COLLAPSED BECAUSE OF THIS
不过在Debug期间,参考了不少其他神犇的AC代码,也学到了各种姿势,算是因祸得福吧……
Vijos1865 NOI2014 魔法森林 LCT维护生成树的更多相关文章
- P2387 [NOI2014]魔法森林 LCT维护最小生成树
\(\color{#0066ff}{ 题目描述 }\) 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 ...
- 【BZOJ 3669】 [Noi2014]魔法森林 LCT维护动态最小生成树
这道题看题意是在求一个二维最小瓶颈路,唯一可行方案就是枚举一维在这一维满足的条件下使另一维最小,那么我们就把第一维排序利用A小的边在A大的情况下仍成立来动态加边维护最小生成树. #include &l ...
- [Luogu P2387] [NOI2014]魔法森林 (LCT维护边权)
题面 传送门:https://www.luogu.org/problemnew/show/P2387 Solution 这题的思想挺好的. 对于这种最大值最小类的问题,很自然的可以想到二分答案.很不幸 ...
- 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 ...
- [NOI2014]魔法森林 LCT
题面 [NOI2014]魔法森林 题解 一条路径的代价为路径上的\(max(a[i]) + max(b[i])\),因为一条边同时有$a[i], b[i]$2种权值,直接处理不好同时兼顾到,所以我们考 ...
- bzoj3669: [Noi2014]魔法森林 lct版
先上题目 bzoj3669: [Noi2014]魔法森林 这道题首先每一条边都有一个a,b 我们按a从小到大排序 每次将一条路劲入队 当然这道题权在边上 所以我们将边化为点去连接他的两个端点 当然某两 ...
- loj2245 [NOI2014]魔法森林 LCT
[NOI2014]魔法森林 链接 loj 思路 a排序,b做动态最小生成树. 把边拆成点就可以了. uoj98.也许lct复杂度写假了..越卡常,越慢 代码 #include <bits/std ...
- bzoj 3669: [Noi2014] 魔法森林 LCT版
Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...
随机推荐
- Linux Shell编程(13)——数字常量
除非一个数字有特别的前缀或符号,否则shell脚本把它当成十进制的数.一个前缀为0的数字是八进制数.一个前缀为0x的数字是十六进制数.一个数用内嵌的#来求值则看成BASE#NUMBER(有范围和符号限 ...
- Qt 与 JavaScript 通信
使用QWebView加载网页后,解决Qt与JavaScript通信的问题: The QtWebKit Bridge :http://qt-project.org/doc/qt-4.8/qtwebkit ...
- 二:java语法基础:
1,关键字:其实就是某种语言赋予了特殊含义的单词. 保留字:其实就是还没有赋予特殊含义,但是准备日后要使用过的单词. 2,标示符:其实就是在程序中自定义的名词.比如类名,变量名,函数名.包含 0-9. ...
- HDOJ1518Square 深搜
Square Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- Show All Running Processes in Linux
ps由于历史的原因,所以很奇特,有些命令必须加"-",比如: ps A 上面的写法是错误的 ********* simple selection ********* ******* ...
- Android开发学习之Adapter
Adapter是指适配器的意思,在Android中,适配器扮演者重要的角色,是UI与Data实现绑定的一个桥梁.Adapter负责创建和显示每个项目的子View和提供对下层数据的访问.支持Adapte ...
- winform DataGridView双击修改单元格的值 分类: DataGridView 2014-08-04 19:39 150人阅读 评论(0) 收藏
定义全局变量 string abcmycode = "";//当前行自编号 bool tf = false;//是否双击 //双击可编辑 private void ...
- Sencha Touch 和 jQuery Mobile 的比较
Sencha Touch 和 jQuery Mobile 的比较 英文原文:Sencha Touch vs jQuery Mobile 标签: Sencha Touch jQuery Mobile 1 ...
- cocos2d&cocos2dx学习资源
汇总一下自己学习Cocos2d和cocos2dx认为比較好的一些资源: 书籍: <iPhone&iPad cocos2d游戏开发实战> Steffen Itterheim < ...
- 支持MySql的数据库自动分表工具DBShardTools发布
支持MySql的数据库自动分表工具DBShardTools发布 前段时间参与了公司的一个项目,这个项目的特点是数据量.访问量都比较大,考虑使用数据库水平分表策略,Google了大半天,竟然没有找到分表 ...