题目描述

为了得到书法大家的真传,小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型守护精灵的个数之和。

输入

第1行包含两个整数N,M,表示无向图共有N个节点,M条边。 接下来M行,第行包含4个正整数Xi,Yi,Ai,Bi,描述第i条无向边。其中Xi与Yi为该边两个端点的标号,Ai与Bi的含义如题所述。 注意数据中可能包含重边与自环。

输出

输出一行一个整数:如果小E可以成功拜访到隐士,输出小E最少需要携带的守护精灵的总个数;如果无论如何小E都无法拜访到隐士,输出“-1”(不含引号)。

样例输入

【输入样例1】
4 5
1 2 19 1
2 3 8 12
2 4 12 15
1 3 17 8
3 4 1 17
【输入样例2】
3 1
1 2 1 1

样例输出

【输出样例1】
32
【样例说明1】
如果小E走路径1→2→4,需要携带19+15=34个守护精灵;
如果小E走路径1→3→4,需要携带17+17=34个守护精灵;
如果小E走路径1→2→3→4,需要携带19+17=36个守护精灵;
如果小E走路径1→3→2→4,需要携带17+15=32个守护精灵。
综上所述,小E最少需要携带32个守护精灵。
【输出样例2】

-1
【样例说明2】
小E无法从1号节点到达3号节点,故输出-1。

提示

2<=n<=50,000

0<=m<=100,000

1<=ai ,bi<=50,000

求一个二维的最小生成树(最小生成森林)中的最大边权,一维的很好做直接按边权排序后加边即可。

那么二维的怎么搞?

我们依旧按第一维排序,这样保证了第一维一定是最小生成树,按排序后顺序枚举所有边,当边两端的点不连通就加入这条边,直接用LCT,link一下即可。

当边两端的点联通,那么我们判断当前枚举边的第二维和1到n路径上第二维边权最大值的关系,如果当前枚举的边小就把那条边删除,加上这条边。

splay要维护第二维边权的最大值,但在LCT上维护边信息并不好做,因此我们将新建一个点tmp来代表边,它的点权就是它代表边的边权。

例如x,y之间有一条边,那么在LCT中就把(x,tmp)和(y,tmp)连接起来。

每次枚举一条边之后判断1和n是否联通,只要联通不管当前边是否被选都用当前边第一维边权和1到n路径上第二维边权最大值来更新答案。

这样更新为什么是对的?

假如这条边选了并且在1到n的路径上,那么这么更新是可以的。

假如这条边选了但不在1到n的路径上,那么说明在这条边选之前1与n就是联通的,这次更新的值一定比答案大,不影响。

假如这条边没选,那这次更新的值也一定比当前答案大,一定不会影响答案。

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n,m;
int ans;
int r[150010];
int v[150010];
int f[150010];
int st[150010];
int s[150010][2];
int num[150010];
struct miku
{
int x,y;
int a,b;
}g[1000010];
bool cmp(miku p,miku q)
{
return p.a<q.a;
}
int get(int rt)
{
return rt==s[f[rt]][1];
}
int is_root(int rt)
{
return rt!=s[f[rt]][0]&&rt!=s[f[rt]][1];
}
void pushup(int rt)
{
num[rt]=rt;
if(v[num[s[rt][0]]]>v[num[rt]])
{
num[rt]=num[s[rt][0]];
}
if(v[num[s[rt][1]]]>v[num[rt]])
{
num[rt]=num[s[rt][1]];
}
}
void pushdown(int rt)
{
if(r[rt])
{
r[s[rt][0]]^=1;
r[s[rt][1]]^=1;
r[rt]^=1;
swap(s[rt][0],s[rt][1]);
}
}
void rotate(int rt)
{
int fa=f[rt];
int anc=f[fa];
int k=get(rt);
if(!is_root(fa))
{
s[anc][get(fa)]=rt;
}
s[fa][k]=s[rt][k^1];
f[s[fa][k]]=fa;
s[rt][k^1]=fa;
f[fa]=rt;
f[rt]=anc;
pushup(fa);
pushup(rt);
}
void splay(int rt)
{
int top=0;
st[++top]=rt;
for(int i=rt;!is_root(i);i=f[i])
{
st[++top]=f[i];
}
for(int i=top;i>=1;i--)
{
pushdown(st[i]);
}
for(int fa;!is_root(rt);rotate(rt))
{
if(!is_root(fa=f[rt]))
{
rotate(get(fa)==get(rt)?fa:rt);
}
}
}
void access(int rt)
{
for(int x=0;rt;x=rt,rt=f[rt])
{
splay(rt);
s[rt][1]=x;
pushup(rt);
}
}
void reverse(int rt)
{
access(rt);
splay(rt);
r[rt]^=1;
}
int find(int rt)
{
access(rt);
splay(rt);
while(s[rt][0])
{
rt=s[rt][0];
}
return rt;
}
void link(int x,int y)
{
reverse(x);
f[x]=y;
}
void cut(int x,int y)
{
reverse(x);
access(y);
splay(y);
f[x]=0;
s[y][0]=0;
pushup(y);
}
int main()
{
ans=1<<30;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
num[i]=i;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&g[i].x,&g[i].y,&g[i].a,&g[i].b);
}
sort(g+1,g+1+m,cmp);
for(int i=1;i<=m;i++)
{
int x=g[i].x;
int y=g[i].y;
if(find(x)!=find(y))
{
v[n+i]=g[i].b;
num[n+i]=n+i;
link(x,n+i);
link(y,n+i);
}
else
{
reverse(x);
access(y);
splay(y);
int val=num[y];
if(v[val]>g[i].b)
{
cut(val,g[val-n].x);
cut(val,g[val-n].y);
num[n+i]=n+i;
v[n+i]=g[i].b;
link(n+i,x);
link(n+i,y);
}
}
if(find(1)==find(n))
{
reverse(1);
access(n);
splay(n);
ans=min(ans,g[i].a+v[num[n]]);
}
}
if(ans==(1<<30))
{
printf("-1");
return 0;
}
printf("%d",ans);
}

最新文章

  1. winform快速开发平台 -&gt; 通用权限管理之动态菜单
  2. SpringMVC,3种不同的URL路由配置方法
  3. Error: cannot find a valid baseurl for repo: rpmfusion-free 解决办法
  4. Docker之功能汇总
  5. coffeeScript 语法总结
  6. MySQL &#183; 特性分析 &#183; MDL 实现分析
  7. air 中的 LocalStore
  8. WCF的配置文件中的要素
  9. php5,Apache在windows 7环境搭建
  10. matlab遗传算法
  11. CString Format 乱码问题
  12. Java 正则表达式详解_正则表达式
  13. 老李推荐: 第3章1节《MonkeyRunner源码剖析》脚本编写示例: MonkeyRunner API使用示例
  14. nginx 部署
  15. cursor()&#160;—&#160;数据库连接操作 python
  16. 并发编程(三)—— ReentrantLock的用法
  17. 开发企业微信打卡API笔记
  18. Java(原码、反码、补码和计算机存储格式)
  19. Hyperledger Fabric链码之二
  20. 多选穿梭框总结 (vue + element)

热门文章

  1. RF
  2. 微软官方的Excel android 移动版的折腾
  3. 使用odoo官方dockerfile 创建最新版镜像
  4. WPF中, 启用添加到RichTextBox中的控件
  5. 使用xshell连接服务器,数字键盘无法使用解决办法
  6. SNMP基础知识
  7. 通过容器提交镜像(docker commit)以及推送镜像(docker push)笔记
  8. zabbix监控主机cpu达到80%后报警
  9. Haproxy+Keepalived高可用环境部署梳理(主主和主从模式)
  10. sheet制作返回按钮