您的位置:首页 > 其它

[NOI2014]魔法森林|动态树

2016-01-08 07:20 211 查看
此题spfa就能A 据说当年sd就有一位神犇用spfa在赛场上强势A了这道题

然而正解貌似是动态树维护生成树

先按a把边排序从小到大枚举插入新边

如果构成环那么把环上的最大的b值的边删掉

------------------------------------------------------

代码异常sb

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
#include<iostream>
#define MX  123456789
using namespace std;
int sc()
{
	int i=0; char c=getchar();
	while(c>'9'||c<'0') c=getchar();
	while(c>='0'&&c<='9') i=i*10+c-'0',c=getchar();
	return i;
}
struct E{int x,y,a,b;} e[111111];
bool rev[155555];
int ch[155555][2],fa[155555],mx[155555],val[155555],st[155555];
int p[155555];
int n,m,ans=MX;
bool operator<(E a,E b){return a.a<b.a;}
bool Root(int x){ return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x; }
int find(int x){return x==p[x]?x:p[x]=find(p[x]);}
void push_down(int x)
{
	if(rev[x])
	{
		rev[x]^=1; rev[ch[x][0]]^=1; rev[ch[x][1]]^=1;
		swap(ch[x][1],ch[x][0]);
	}
}
void push_up(int x)
{
	int l=ch[x][0],r=ch[x][1];  mx[x]=x;
	if(val[mx[l]]>val[mx[x]])mx[x]=mx[l];
	if(val[mx[r]]>val[mx[x]])mx[x]=mx[r];
}
void rotate(int x)
{
	int y=fa[x],z=fa[y],l,r;
	if(ch[y][0]==x) l=0; else l=1; r=l^1;
	if(!Root(y))
	{
		if(ch[z][0]==y) ch[z][0]=x; else ch[z][1]=x;
	}
	fa[x]=z; fa[y]=x; fa[ch[x][r]]=y;
	ch[y][l]=ch[x][r]; ch[x][r]=y; 
	push_up(y); push_up(x);
}
void splay(int x)
{
	int top=0; st[++top]=x;
	for(int i=x;!Root(i);i=fa[i]) st[++top]=fa[i];
	while(top)push_down(st[top--]);
	while(!Root(x))
	{
		int y=fa[x],z=fa[y];
		if(!Root(y))
		{
			if(ch[z][0]==y^ch[y][0]==x) rotate(y);
			else rotate(x);
		}
		rotate(x);
	}
}
void access(int x)
{
	for(int t=0;x;t=x,x=fa[x])
	    splay(x),ch[x][1]=t,push_up(x);
}
void make_root(int x){access(x),splay(x),rev[x]=1;}
void link(int x,int y){make_root(x),fa[x]=y;}
void cut(int x,int y){make_root(x),access(y),splay(y),ch[y][0]=fa[x]=0,push_up(y);}
int query(int x,int y)
{
	make_root(x),access(y),splay(y);
	return mx[y];
}
int main()
{
	n=sc(),m=sc();
	for(int i=1;i<=n;i++)p[i]=i;
	for(int i=1;i<=m;i++) e[i].x=sc(),e[i].y=sc(),e[i].a=sc(),e[i].b=sc();
	sort(e+1,e+m+1);
	for(int i=1;i<=m;i++)
	{
		int x=e[i].x,y=e[i].y,a=e[i].a,b=e[i].b;
		if(find(x)==find(y))
		{
			int t=query(x,y);
			if(val[t]>e[i].b) cut(t,e[t-n].x),cut(t,e[t-n].y);
			else
			{
				if(find(1)==find(n)) ans=min(ans,a+val[query(1,n)]);
				continue;
			}
		}
		else p[find(x)]=find(y);
		val[n+i]=b; mx[n+i]=n+i;
		link(x,n+i),link(y,n+i);
		if(find(1)==find(n)) ans=min(ans,a+val[query(1,n)]);
	}
	if(ans==MX) puts("-1");
	else cout<<ans;
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: