首页 > 其他分享 >bzoj 3669 魔法森林

bzoj 3669 魔法森林

时间:2023-03-25 16:07:42浏览次数:59  
标签:ch int 魔法 3669 精灵 fa inline 守护 bzoj


3669: [Noi2014]魔法森林

Time Limit: 30 Sec   Memory Limit: 512 MB

Submit: 2690  

Solved: 1667

Submit][Status][Discuss]

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型守护精灵的个数之和。

Input

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

Output

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

Sample Input

【输入样例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

Sample Output

【输出样例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。

HINT

2<=n<=50,000

0<=m<=100,000

1<=ai ,bi<=50,000

Source

【分析】

Wc 水管 的水化水化版...

【代码】

//NOI 2014 膜法森林
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=200005;
int n,m,top,ans=1e9+7;
struct edge {int l,r,a,b;} e[mxn];
int f[mxn],ch[mxn][2],rev[mxn],st[mxn],mx[mxn],val[mxn];
inline bool comp(edge x,edge y) {return x.a==y.a?x.b<y.b:x.a<y.a;}
inline bool isroot(int x) {return ch[f[x]][0]!=x && ch[f[x]][1]!=x;}
inline int get(int x) {return ch[f[x]][1]==x;}
inline void update(int x)
{
	mx[x]=x;
	int l=ch[x][0],r=ch[x][1];
	if(val[mx[l]]>val[mx[x]]) mx[x]=mx[l];
	if(val[mx[r]]>val[mx[x]]) mx[x]=mx[r];
}
inline void reverse(int x) {if(!x) return;rev[x]^=1,swap(ch[x][0],ch[x][1]);}
inline void pushdown(int x) {if(rev[x]) reverse(ch[x][0]),reverse(ch[x][1]),rev[x]=0;}
inline void rotate(int x)
{
	pushdown(x);
	int fa=f[x],fafa=f[fa],which=get(x);
	if(!isroot(fa)) ch[fafa][ch[fafa][1]==fa]=x;f[x]=fafa;
	ch[fa][which]=ch[x][which^1],f[ch[fa][which]]=fa;
	ch[x][which^1]=fa,f[fa]=x;
	update(fa),update(x);
}
inline void splay(int x)
{
	st[top=1]=x;
	for(int i=x;!isroot(i);i=f[i]) st[++top]=f[i];
	for(int i=top;i;i--) pushdown(st[i]);
	for(int fa;!isroot(x);rotate(x))
	  if(!isroot(fa=f[x])) rotate(get(x)==get(fa)?fa:x);
}
inline void access(int x) {for(int y=0;x;y=x,x=f[x]) splay(x),ch[x][1]=y,update(x);}
inline void makeroot(int x) {access(x),splay(x),reverse(x);}
inline int find(int x) {access(x),splay(x);while(ch[x][0]) x=ch[x][0];return x;}
inline void split(int x,int y) {makeroot(x),access(y),splay(y);}
inline void link(int x,int y) {makeroot(x),f[x]=y;}
inline void cut(int x,int y) {split(x,y),ch[y][0]=f[x]=0;}
int main()
{
	int i,j;
	scanf("%d%d",&n,&m);
	fo(i,1,m) scanf("%d%d%d%d",&e[i].l,&e[i].r,&e[i].a,&e[i].b);
	sort(e+1,e+m+1,comp);
	fo(i,1,m) 
	{
		val[i+n]=e[i].b;
		int u=e[i].l,v=e[i].r;
		if(find(u)!=find(v))
		  link(i+n,u),link(i+n,v);
		else
		{
			split(u,v);
			int tmp=mx[v];  //u->v路径最大权节点
			if(val[i+n]<val[tmp])
			{
				cut(tmp,e[tmp-n].l),cut(tmp,e[tmp-n].r);
				link(i+n,u),link(i+n,v);
			}
		}
		if(find(1)==find(n)) split(1,n),ans=min(ans,e[i].a+val[mx[n]]);
	}
	printf("%d\n",ans==1e9+7?-1:ans);
	return 0;
}



标签:ch,int,魔法,3669,精灵,fa,inline,守护,bzoj
From: https://blog.51cto.com/u_15967757/6149509

相关文章

  • bzoj 2843 极地旅行社
    2843:极地旅行社TimeLimit: 10Sec  MemoryLimit: 256MBSubmit: 771  Solved: 473[Submit][Status][Discuss]Description不久之前,Mirko建立了一......
  • bzoj 2555 SubString
    2555:SubStringTimeLimit: 30Sec  MemoryLimit: 512MBSubmit: 2611  Solved: 784[Submit][Status][Discuss]Description      懒得写背景......
  • bzoj 2157 旅游
    2157:旅游TimeLimit:10Sec  MemoryLimit:259MBSubmit:1649  Solved:725[Submit][Status][Discuss]DescriptionRay乐忠于旅游,这次他来到了T城。......
  • bzoj 2631 tree
    2631:treeTimeLimit: 30Sec  MemoryLimit: 128MBSubmit: 4429  Solved: 1488[Submit][Status][Discuss]Description一棵n个点的树,每个点的初始......
  • bzoj 2049 [Sdoi2008]Cave 洞穴勘测
    2049:[Sdoi2008]Cave洞穴勘测TimeLimit: 10Sec  MemoryLimit: 259MBSubmit: 8714  Solved: 4143[Submit][Status][Discuss]Description辉辉热衷......
  • bzoj 2806 [Ctsc2012]Cheat
    2806:[Ctsc2012]CheatTimeLimit: 20Sec  MemoryLimit: 256MBSubmit: 1324  Solved: 676[Submit][Status][Discuss]DescriptionInput第一行两个......
  • bzoj 3879 SvT
    3879:SvTTimeLimit: 30Sec  MemoryLimit: 512MBSubmit: 764  Solved: 297[Submit][Status][Discuss]Description(我并不想告诉你题目名字是什么鬼)有一......
  • bzoj 2594 [Wc2006]水管局长数据加强版
    2594:[Wc2006]水管局长数据加强版TimeLimit: 25Sec  MemoryLimit: 128MBSubmit: 3509  Solved: 1119[Submit][Status][Discuss]DescriptionSC省M......
  • bzoj 3091 城市旅行
    3091:城市旅行TimeLimit: 10Sec  MemoryLimit: 128MBSubmit: 1697  Solved: 565[Submit][Status][Discuss]DescriptionInputOutputSampleI......
  • bzoj 2006 [NOI2010] 超级钢琴 线段树求区间极值+优先队列
    挺神奇的一道题,唯一想不通的是为什么放在主席树的题单里..首先暴力找出所有的合法区间显然是不可能的。考虑怎么贪心,假如固定每个L作为左端点,那么合法的区间就是[L+l-1,L......