Title Description: https://www.luogu.org/problem/P2387
Analysis: is the maximum value the minimum requirements of the subject, the first thought two points, but there are two variables do not, then obviously think of a Greedy: UV for two points, edges between them a small value, b value is also small side definitely better. So we first side by a value, then by b value to maintain the minimum spanning tree. For a newly inserted side, if it has appeared in the unruly minimum spanning tree, we query the largest ring in the side edge is greater than this, if it is, then cut off the original that edge. So what I Fengyun how to maintain minimum spanning tree it? Obviously the LCT. But we want to maintain that boundary, how do it? A routine is to build a multi-point, then the value of the point assigned to the right side, the beginning and end, respectively, can be connected to this edge.
Details: 1. no details, do not write like hanging.
Attach Code:
#include <cstdio> #include <the iostream> #include <algorithm> the using namespace STD; // Given a graph, each edge has two ab & weights, to find a path to the starting point of // such that this path on a maximum value and the maximum value and the minimum b const int MAXN = 50005 , MAXM = 200005 ; int n-, m; struct Edge { int U, V, a, b; } Edge [MAXM]; int FA [MAXM ]; struct the Node { int max, Val, Son [ 2 ], FA; BOOL flag_reverse; } Node [MAXM << . 1 ]; int ans=0x3f3f3f; int stk[MAXM<<1]; inline int read(){ int ret=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-f;c=getchar();} while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} return ret*f; } void readIn(int i){ edge[i].u=read();edge[i].v=read();edge[i].a=read();edge[i].b=read(); edge[i+1].u=edge[i].u;edge[i+1].v=edge[i].v;edge[i+1].a=edge[i].a;edge[i+1].b=edge[i].b; } int union_find(int x){ if(x==fa[x]) return x; else return fa[x]=union_find(fa[x]); } void update(int x){ node[x].max=x; int lson=node[x].son[0],rson=node[x].son[1]; if(lson&&node[node[lson].max].val>node[node[x].max].val) node[x].max=node[lson].max; if(rson&&node[node[rson].max].val>node[node[x].max].val) node[x].max=node[rson].max; } void pushdown(int x){ if(node[x].flag_reverse){ int lson=node[x].son[0],rson=node[x].son[1]; node[lson].flag_reverse^=1; node[rson].flag_reverse^=1; node[x].flag_reverse^=1; swap(node[x].son[0],node[x].son[1]); } } int get(int x){ return x==node[node[x].fa].son[0]||x==node[node[x].fa].son[1]; } int check(int x){ return x==node[node[x].fa].son[1]; } void rotate(int x){ int y=node[x].fa,z=node[y].fa,d=check(x),xx=node[x].son[d^1]; node[y].son[d]=xx;if(xx) node[xx].fa=y; if(get(y)) node[z].son[check(y)]=x;node[x].fa=z; node[x].son[d^1]=y;node[y].fa=x; update(y);update(x); } void splay(int x){ int y=x,top=0;stk[++top]=y; while(get(y)) stk[++top]=y=node[y].fa; while(top) pushdown(stk[top--]); while(get(x)){ int y=node[x].fa; if(get(y)) rotate(check(x)==check(y)?y:x); rotate(x); } } void access(int x){ int xx=0; while(x){ splay(x); node[x].son[1]=xx; xx=x; update(x); x=node[x].fa; } } int find(int x){ access(x);splay(x); while(node[x].son[0]) x=node[x].son[0]; return x; } void make_root(int x){ access(x);splay(x); node[x].flag_reverse^=1; } void link(int x,int y){ make_root(x);if(find(y)!=x) node[x].fa=y; } void split(int x,int y){ make_root(x);access(y);splay(y); } void cut(int x,int y){ split(x,y); if(find(y)==x&&!node[x].son[1]&&node[x].fa==y) node[x].fa=node[y].son[0]=0; } int query(int x,int y){ split(x,y); return node[y].max; } void work(){ for(int i=1;i<=m;++i) fa[i]=i; for(int i=1;i<=m;i++){ int u=edge[i].u,v=edge[i].v; if(union_find(u)==union_find(v)){ int t=query(u,v); if(edge[i].b<node[t].val){ cut(t,edge[t-n].u); cut(t,edge[t-n].v); } else{ if(union_find(1)==union_find(n)) ans=min(ans,edge[i].a+node[query(1,n)].val); continue; } } else fa[union_find(u)]=union_find(v); node[i+n].max=i+n;node[i+n].val=edge[i].b; link(u,i+n);link(i+n,v); if(union_find(1)==union_find(n)) ans=min(ans,edge[i].a+node[query(1,n)].val); } if(ans!=0x3f3f3f) printf("%d",ans); else printf("-1"); } bool cmp(Edge A,Edge B){ return A.a<B.a; } int main(){ n=read();m=read();m<<=1; for(int i=1;i<=m;i+=2) readIn(i); sort(edge+1,edge+m+1,cmp); work(); return 0; }