Description

为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士。魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M。初始时小E同学在号节点1,隐士则住在号节点N。小E需要通过这一片魔法森林,才能够拜访到隐士。
魔法森林中居住了一些妖怪。每当有人经过一条边的时候,这条边上的妖怪就会对其发起攻击。幸运的是,在号节点住着两种守护精灵:A型守护精灵与B型守护精灵。小E可以借助它们的力量,达到自己的目的。
只要小E带上足够多的守护精灵,妖怪们就不会发起攻击了。具体来说,无向图中的每一条边Ei包含两个权值Ai与Bi。若身上携带的A型守护精灵个数不少于Ai,且B型守护精灵个数不少于Bi,这条边上的妖怪就不会对通过这条边的人发起攻击。当且仅当通过这片魔法森林的过程中没有任意一条边的妖怪向小E发起攻击,他才能成功找到隐士。
由于携带守护精灵是一件非常麻烦的事,小E想要知道,要能够成功拜访到隐士,最少需要携带守护精灵的总个数。守护精灵的总个数为A型守护精灵的个数与B型守护精灵的个数之和。

题解:

用LinkCutTree维护最小生成树。首先按A从小到大排序,若A相同则按B从小到大排序。然后我们每次加一条边,若边的两端点已经相连,则在这两端点的路径中寻找B的最大值,若当前边的B值比这个最大值小,就删掉那条边,加入当前边;若边的两端点没有相连,则直接连起来。每次对一条边操作完后判断1、n是否相连,若相连则更新答案。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=150010;
int n,m,ans=(1<<30);
int son[maxn][2],fa[maxn],Max[maxn],sta[maxn],val[maxn];
bool rev[maxn];
struct Edge{int x,y,A,B;}e[maxn*2];
bool cmp(Edge a,Edge b)
{if(a.A==b.A)return a.B<b.B;return a.A<b.A;
}
void push_up(int x)
{Max[x]=x;//这句话很重要! int lc=son[x][0],rc=son[x][1];if(val[Max[lc]]>val[Max[x]])Max[x]=Max[lc];if(val[Max[rc]]>val[Max[x]])Max[x]=Max[rc];
}
void push_down(int x)
{if(rev[x]){rev[x]=false;swap(son[x][0],son[x][1]);rev[son[x][0]]^=1;rev[son[x][1]]^=1;}
}
bool is_root(int x)
{if(son[fa[x]][0]==x)return false;if(son[fa[x]][1]==x)return false;return true;
}
void rotate(int x)
{int y=fa[x],z=fa[y];int a=son[y][1]==x,b=son[z][1]==y;if(!is_root(y))son[z][b]=x;fa[x]=z;int g=son[x][!a];son[y][a]=g;fa[g]=y;son[x][!a]=y;fa[y]=x;push_up(y);push_up(x);
}
void pre(int x)
{if(!is_root(x))pre(fa[x]);push_down(x);
}
void splay(int x)
{pre(x);while(!is_root(x)){int y=fa[x],z=fa[y];if(!is_root(y)){if((son[y][1]==x)==(son[z][1]==y))rotate(y);else rotate(x);}rotate(x);}push_up(x);
}
void access(int x)
{int last=0;while(x){splay(x);son[x][1]=last;push_down(x);last=x;x=fa[x];}
}
void make_root(int x)
{access(x);splay(x);rev[x]^=1;
}
int find_root(int x)
{access(x);splay(x);while(son[x][0])x=son[x][0];return x;
}
void split(int x,int y)
{make_root(x);access(y);splay(y);
}
void link(int x,int y)
{make_root(x);fa[x]=y;
}
void cut(int x,int y)
{split(x,y);son[y][0]=fa[x]=0;push_up(y);
}
int query(int x,int y)
{split(x,y);return Max[y];
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=m;i++)scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].A,&e[i].B);sort(e+1,e+1+m,cmp);for(int i=0;i<=n;i++)Max[i]=val[i]=0;for(int i=1;i<=m;i++){val[n+i]=e[i].B;int fx=find_root(e[i].x),fy=find_root(e[i].y);if(fx==fy){int k=query(e[i].x,e[i].y);if(val[k]>e[i].B){cut(e[k-n].x,k);cut(k,e[k-n].y);link(e[i].x,n+i);link(n+i,e[i].y);} }else link(e[i].x,n+i),link(n+i,e[i].y);if(find_root(1)==find_root(n)){int k=query(1,n);ans=min(ans,e[i].A+val[k]);}}if(ans==(1<<30))puts("-1");else printf("%d",ans);
}

[BZOJ]3669: [Noi2014]魔法森林 lct相关推荐

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

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

  2. 图论 BZOJ 3669 [Noi2014]魔法森林

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

  3. loj2245 [NOI2014]魔法森林 LCT

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

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

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

  5. NOI2014魔法森林--LCT

    题意:求一条1->n的路径,使得路径上的MAXA+MAXB最小. 做法:以a值从小到大对边排序,动态加边,维护一个最小生成树就行了.如果两个端点不连通,则直接加上,否则就把这个环上b值最大的边删 ...

  6. [BZOJ3669]-[Noi2014]魔法森林-LCT+并查集

    说在前面 刚刚去写了一道SPFA+网络流的糅合题,1A了 闲着没事干开始翻起了status,发现有人在做水管局长,哇这不是LCT嘛! 然后回头看了一下自己写过的寥寥无几的LCT的题,发现都快要忘了 于 ...

  7. [LCT动态树] [NOI2014]魔法森林,[ZJOI2018]历史

    [NOI2014] 魔法森林 题目 按照aaa精灵从小到大排序 按顺序插入每一条边 加入第iii条边后的最小代价为a[i]a[i]a[i]加上从111到nnn的所有路径中最大bbb最小的路径代价 维护 ...

  8. 【bzoj3669】[Noi2014]魔法森林【LCT】

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

  9. 神spfa [Noi2014]魔法森林

    问题 G: [Noi2014]魔法森林 时间限制: 30 Sec  内存限制: 512 MB 题目描述 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个 ...

最新文章

  1. python tk 持续请求接口获取数据_tk数据获得的问题!!
  2. 河北职称计算机2012试题,2012年河北省职称计算机考试试题及答案.doc
  3. 分布式内存数据库---redis配置文件常用配置介绍
  4. 浮岛物语(FORAGER): 在 GameMaker 中做优化
  5. 搭载敏捷飞天底座,阿里云专有云敏捷版全面升级
  6. PHP导出成word文档
  7. 眼坐标系和世界坐标系的相互转换
  8. python的namedtuple
  9. 【Centos】【Python】【Flask】阿里云上部署一个 flask 项目
  10. C#.NET自定义报表数据打印
  11. 中国移动手机支付开放平台网站服务协议
  12. redis通过hscan导入大hash key
  13. Java解压ZIP、RAR文件
  14. [ESP32/ESP8266专题笔记-5] ESP8266开发板-Micropython-串口控制继电器
  15. srand((unsigned int)time(NULL))的理解(C语言)
  16. Android Studio系统状态栏,设置setSmallIcon通知图标无效问题及解决方案
  17. css_属性选择器(根据属性名或属性值设定指定样式)
  18. 蓝桥杯2020年第十一届C/C++B组(第一次)省赛习题题解
  19. 赚钱App研究之格式转换类app
  20. k8s镜像一直failed pull images

热门文章

  1. AutoCAD图纸统计工具
  2. 百度只为营销而存在?
  3. 小白围观,超级牛的STM32 BLDC直流电机控制器设计
  4. 谈谈计算机网络与通信
  5. 前端监控系列1| 字节的前端监控SDK是怎样设计的
  6. Mysql学习笔记——mysql服务在win上安装与启动
  7. Xamarin跨线程
  8. oracle手机号码检验字数_oracle根据检验规则获取正确身份证号
  9. 赛马网基本算法之--路灯
  10. 使用Telnet收发163邮件