bzoj 3669
思想基本同bzoj 2594,但是多了一步
首先我们发现这时的边有两个属性了,因此我们考虑先去掉其中一者的限制
我们把所有边按$a$大小排序,然后从小到大加入维护的最小生成树
每次加边时都按照$b$的大小操作bzoj 2594,然后更新答案即可
如果始终不联通输出-1
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <map> using namespace std; struct Ques { int x,y,typ,num; }q[1000005]; struct Edge { int l,r,v1,v2; friend bool operator < (Edge a,Edge b) { return a.v1==b.v1?a.v2<b.v2:a.v1<b.v1; } }edge[1000005]; map <pair<int,int>,int> M; int n,m,Q; int ch[2000005][2]; int vis[2000005]; int maxx[2000005]; int val[2000005]; int f[2000005]; int fl[2000005]; int ret[2000005]; void update(int x) { maxx[x]=val[x]; if(edge[maxx[ch[x][0]]].v2>edge[maxx[x]].v2)maxx[x]=maxx[ch[x][0]]; if(edge[maxx[ch[x][1]]].v2>edge[maxx[x]].v2)maxx[x]=maxx[ch[x][1]]; } bool be_root(int x) { if(ch[f[x]][0]==x||ch[f[x]][1]==x)return 0; return 1; } void pushdown(int x) { if(fl[x]) { swap(ch[ch[x][0]][0],ch[ch[x][0]][1]); swap(ch[ch[x][1]][0],ch[ch[x][1]][1]); fl[ch[x][0]]^=1,fl[ch[x][1]]^=1; fl[x]=0; } } void repush(int x) { if(!be_root(x))repush(f[x]); pushdown(x); } void rotate(int x) { int y=f[x],z=f[y],k=(ch[y][1]==x); if(!be_root(y))ch[z][ch[z][1]==y]=x; f[x]=z; ch[y][k]=ch[x][!k],f[ch[x][!k]]=y; ch[x][!k]=y,f[y]=x; update(y),update(x); } void splay(int x) { repush(x); while(!be_root(x)&&x) { int y=f[x],z=f[y]; if(!be_root(y)&&y) { if((ch[y][1]==x)^(ch[z][1]==y))rotate(x); else rotate(y); } rotate(x); } update(x); } void access(int x) { int y=0; while(x) { splay(x); ch[x][1]=y; update(x); y=x,x=f[x]; } } void makeroot(int x) { access(x),splay(x); swap(ch[x][0],ch[x][1]),fl[x]^=1; } void link(int x,int y) { makeroot(x); f[x]=y; } void split(int x,int y) { makeroot(x),access(y),splay(y); } void cut(int x,int y) { split(x,y),ch[y][0]=f[x]=0,update(y); } int findf(int x) { access(x),splay(x),pushdown(x); while(ch[x][0])x=ch[x][0],pushdown(x); return x; } inline int read() { int f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int main() { n=read(),m=read(); for(int i=1;i<=m;i++) { edge[i].l=read(),edge[i].r=read(),edge[i].v1=read(),edge[i].v2=read(); if(edge[i].l>edge[i].r)swap(edge[i].l,edge[i].r); } sort(edge+1,edge+m+1); int ans=0x3f3f3f3f; for(int i=1;i<=m;i++)val[i+n]=maxx[i+n]=i; for(int i=1;i<=m;i++) { int f1=findf(edge[i].l),f2=findf(edge[i].r); if(f1==f2) { split(edge[i].l,edge[i].r); if(edge[maxx[edge[i].r]].v2>edge[i].v2) { int t=maxx[edge[i].r]; cut(edge[t].l,t+n),cut(edge[t].r,t+n); link(edge[i].l,i+n),link(edge[i].r,i+n); } }else link(edge[i].l,i+n),link(edge[i].r,i+n); int ff1=findf(1),ff2=findf(n); if(ff1==ff2) { split(1,n); ans=min(ans,edge[i].v1+edge[maxx[n]].v2); } } if(ans==0x3f3f3f3f)printf("-1\n"); else printf("%d\n",ans); return 0; }