题意:
给出一个n个点m条边的无向图,现在要从点1走到点n;
每条边有两个参数a和b,经过这条边必须分别要带不小于a和b的两种权值;
求携带的最小ab权值和,若无解输出-1;
2<=n<=50000,0<=m<=100000
题解:
挺神的一道题。。
考虑路径上最小的b的权值,只需要对b做一次最小生成树就可以了;
但是a的权值怎么办呢?
枚举!
枚举每次经过的最大的a权值,然后求b的最小生成树,更新答案;
但是为了保证最大,要按a权值升序排;
加边就是维护最小生成树啦,LCT!
正确性似乎不用太解释?
然后写一写调一调就好了;
我因为没判断弹的边和要加的边的大小关系WA了一发;
复杂度就是O(mlogm+mlogn)吧;
LCT最近刷到意识模糊。。。
代码:
#include<stdio.h> #include<string.h> #include<algorithm> #define N 51000 #define which(x) (ch[fa[x]][1]==x) using namespace std; struct node { int x,y,a,b; }eg[N<<1]; int fa[N*3],ch[N*3][2],val[N*3],ma[N*3]; bool rt[N*3],rev[N*3]; inline int read() { int x=0;char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x; } int cmp(node a,node b) { if(a.a==b.a) return a.b<b.b; return a.a<b.a; } void Pushup(int x) { ma[x]=val[x]>max(val[ma[ch[x][0]]],val[ma[ch[x][1]]])?x: (val[ma[ch[x][0]]]>val[ma[ch[x][1]]]?ma[ch[x][0]]:ma[ch[x][1]]); } void reverse(int x) { swap(ch[x][0],ch[x][1]); rev[x]^=1; } void Pushdown(int x) { if(rev[x]) { reverse(ch[x][0]); reverse(ch[x][1]); rev[x]=0; } } void down(int x) { if(!rt[x]) down(fa[x]); Pushdown(x); } void Rotate(int x) { int f=fa[x]; bool k=which(x); if(rt[f]) rt[f]^=rt[x]^=1; else ch[fa[f]][which(f)]=x; ch[f][k]=ch[x][!k]; ch[x][!k]=f; fa[ch[f][k]]=f; fa[x]=fa[f]; fa[f]=x; Pushup(f); Pushup(x); } void Splay(int x) { down(x); while(!rt[x]) { int f=fa[x]; if(rt[f]) { Rotate(x); return ; } if(which(x)^which(f)) Rotate(x); else Rotate(f); Rotate(x); } } void access(int x) { int y=0; while(x) { Splay(x); rt[ch[x][1]]=1,rt[y]=0; ch[x][1]=y; Pushup(x); y=x,x=fa[x]; } } void Mtr(int x) { access(x); Splay(x); reverse(x); } bool judge(int x,int y) { Mtr(x); access(y); Splay(x); while(!rt[y]) y=fa[y]; return x==y; } void Link(int x,int y) { Mtr(x); fa[x]=y; } void Cut(int t,int x,int y) { Mtr(t); access(x); Splay(t); rt[ch[t][1]]=1; fa[ch[t][1]]=0; ch[t][1]=0; access(y); Splay(t); rt[ch[t][1]]=1; fa[ch[t][1]]=0; ch[t][1]=0; } int main() { int n,m,i,j,k,x,y,ans; scanf("%d%d",&n,&m); for(i=1;i<=m;i++) { eg[i].x=read(),eg[i].y=read(),eg[i].a=read(),eg[i].b=read(); } sort(eg+1,eg+1+m,cmp); for(i=1;i<=n;i++) rt[i]=1,ma[i]=i; for(i=1,ans=0x3f3f3f3f;i<=m;i++) { x=eg[i].x,y=eg[i].y; if(x==y) continue; rt[i+n]=1,val[i+n]=eg[i].b,ma[i+n]=i+n; if(judge(x,y)) { if(val[ma[x]]>eg[i].b) Cut(ma[x],x,y),Link(i+n,x),Link(i+n,y); } else Link(i+n,x),Link(i+n,y); if(judge(1,n)) ans=min(ans,eg[i].a+val[ma[1]]); } if(ans==0x3f3f3f3f) puts("-1"); else printf("%d\n",ans); return 0; }
时间: 2024-10-27 03:51:50