玄关:MnZn求助lct维护边权
查看原帖
玄关:MnZn求助lct维护边权
311306
dk_qwq楼主2023/11/4 13:30

根本不会,调了好长时间了

#include<iostream>
#include<cstdio>
#include<vector>
#define pb push_back
using namespace std;
namespace INPUT{
	char buf[1<<20],*p1,*p2;
	#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
}
using namespace INPUT;
template<typename T>
T read(){
	T x=0,p=1;
	char ch=gc();
	for(;ch<'0'||ch>'9';ch=gc())
		if(ch=='-') p=-1;
	for(;'0'<=ch&&ch<='9';ch=gc())
		x=(x<<3)+(x<<1)+(ch^48);
	return x*p;
}
#include<algorithm>
#define ll long long
#include<utility>
#define MP make_pair

//DSU wait for realize
template<size_t N>
struct DSU{
	int fa[N];
	int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
	bool Union(int u,int v){
		u=find(u),v=find(v);
		if(u==v) return false;
		fa[v]=u;
		return true;
	}
	void init(int _n){
		for(int i=1;i<=_n;i++) fa[i]=i;
	}
};

template<size_t N>
struct LCT{
	int f[N],ls[N],rs[N],lz[N];
	pair<int,int> val[N],Max[N];//val/id
	void pushup(int x){
		Max[x]=val[x];
		Max[x]=max(Max[x],max(Max[ls[x]],Max[rs[x]]));
	}
	void pushdown(int x){
		if(lz[x]){
			swap(ls[x],rs[x]);
			if(ls[x]) lz[ls[x]]^=1;
			if(rs[x]) lz[rs[x]]^=1;
			lz[x]=0;
		}
	}
	int get(int x){
		if(ls[f[x]]==x) return 0;
		if(rs[f[x]]==x) return 1;
		return -1;
	}
	void connect(int x,int y,int opt){
		f[x]=y;
		if(opt==0) ls[y]=x;
		if(opt==1) rs[y]=x;
	}
	void rotate(int x){
		int y=f[x],z=f[y];
		int opx=get(x),opy=get(y);
		int u=(opx==0?rs[x]:ls[x]);
		connect(u,y,opx),connect(y,x,opx^1);
		connect(x,z,opy);
		pushup(y),pushup(x);
	}
	void pushall(int x){
		if(get(x)!=-1) pushall(f[x]);
		pushdown(x);
	}
	void splay(int x){
		pushall(x);
		while(get(x)!=-1){
			if(get(f[x])==-1) rotate(x);
			else if(get(f[x])==get(x)) rotate(f[x]),rotate(x);
			else rotate(x),rotate(x);
		}
	}
	void access(int x){
		int pre=0;
		while(x){
			splay(x),rs[x]=pre;
			pushup(x);
			pre=x,x=f[x];
		}
	}
	void makeroot(int x){
		access(x),splay(x);
		swap(ls[x],rs[x]);
		if(ls[x]) lz[ls[x]]^=1;
		if(rs[x]) lz[rs[x]]^=1;
	}
	int findroot(int x){
		access(x),splay(x);
		while(ls[x]) pushdown(x),x=ls[x];
		splay(x);
		return x;
	}
	void split(int x,int y){
		makeroot(x),access(y),splay(y);
	}
	bool link(int x,int y){
		makeroot(x);
		if(findroot(y)==x) return false;
		f[x]=y;
		return true;
	}
	bool cut(int x,int y){
		if(findroot(x)!=findroot(y)) return false;
		split(x,y);
		if(f[x]!=y||rs[x]) return false;
		f[x]=ls[y]=0;
		pushup(x);
		return true;
	}
};
const int N=5e4+5;
LCT<N> lct;int tot;
DSU<N> dsu;
int n,m;
struct Edge{int u,v;int A,B;};
vector<Edge>edges;
int main(){
	freopen("P2387.in","r",stdin);
	freopen("P2387.out","w",stdout);
	n=read<int>(),m=read<int>();
	for(int i=1;i<=m;i++){
		int u=read<int>(),v=read<int>();
		int A=read<int>(),B=read<int>();
		edges.pb({u,v,A,B});
	}
	sort(edges.begin(),edges.end(),[](Edge a,Edge b){
		return a.A<b.A;
	});
	int ans=1e9+5;

	dsu.init(n),tot=n;

	for(auto ed:edges){
		if(ed.u==ed.v) continue;
		if(dsu.Union(ed.u,ed.v)){
			int cur=++tot;
			lct.val[cur]=MP(ed.B,cur),lct.pushup(cur);
			lct.link(ed.u,cur),lct.link(ed.v,cur);
		}
		else {
			lct.split(ed.u,ed.v);
			if(lct.Max[ed.v].first>ed.B){
				int cur=++tot,pre=lct.Max[ed.v].second;
				lct.cut(pre,ed.u),lct.cut(pre,ed.v);
				lct.val[cur]=MP(ed.B,cur),lct.pushup(cur);
				lct.link(cur,ed.u),lct.link(cur,ed.v);
			}
		}
		if(lct.findroot(1)==lct.findroot(n)) {
			lct.split(1,n);
			ans=min(ans,ed.A+lct.Max[n].first);
		}
	}
	if(lct.findroot(1)!=lct.findroot(n)) puts("-1");
	else printf("%d\n",ans);
}
2023/11/4 13:30
加载中...