这道题有两个权值 我们把所有边按权值a排序 剩下的边都看成点放进一个LCT中 维护每一节点的最大权值点的位置 枚举所有的边 如果u, v连通 则删去最大的边 加入这条边
否则直接加入这条边 当发现1和n连通的时候更新答案
开数组的时候把val 和 MAX开成bool也是醉了orz
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#define SF scanf
#define PF printf
using namespace std;
typedef long long LL;
const int MAXN = 50000;
const int MAXM = 100000;
const int MAXNODE = 150000;
const int INF = 1234567890;
struct LCT {
int ch[MAXNODE+10][2], fa[MAXNODE+10], MAX[MAXNODE+10];
int val[MAXNODE+10], Q[MAXNODE+10];
bool rev[MAXNODE+10];
bool isroot(int x) {
return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
}
void up(int x) {
int ls = ch[x][0], rs = ch[x][1];
MAX[x] = x;
if(val[MAX[ls]] > val[MAX[x]]) MAX[x] = MAX[ls];
if(val[MAX[rs]] > val[MAX[x]]) MAX[x] = MAX[rs];
}
void pushdown(int x) {
int &ls = ch[x][0], &rs = ch[x][1];
if(rev[x]) {
rev[x] ^= 1; rev[ls] ^= 1; rev[rs] ^= 1;
swap(ls, rs);
}
}
void Rotate(int x) {
int y = fa[x], z = fa[y];
bool d = x == ch[y][0];
if(!isroot(y)) ch[z][y == ch[z][1]] = x;
fa[x] = z; fa[y] = x; fa[ch[x][d]] = y;
ch[y][!d] = ch[x][d]; ch[x][d] = y;
up(y);
}
void splay(int x) {
int top = 0; Q[++top] = x;
for(int i = x; !isroot(i); i = fa[i]) Q[++top] = fa[i];
for(int i = top; i; i--) pushdown(Q[i]);
while(!isroot(x)) {
int y = fa[x];
if(!isroot(y)) Rotate((ch[y][0] == x ^ ch[fa[y]][0] == y) ? x : y);
Rotate(x);
}
up(x);
}
void access(int x) {
int t = 0;
while(x) {
splay(x);
ch[x][1] = t;
t = x; x = fa[x];
}
}
void makeroot(int x) {
access(x); splay(x); rev[x] ^= 1;
}
void link(int x, int y) {
makeroot(x); fa[x] = y;
}
void cut(int x, int y) {
makeroot(x); access(y); splay(y); ch[y][0] = fa[x] = 0;
}
int query(int x, int y) {
makeroot(x); access(y); splay(y); return MAX[y];
}
} sp;
int fa[MAXNODE+10], n, m, ans = INF;
int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
struct Node {
int u, v, a, b;
bool operator < (const Node &t) const {
return a < t.a;
}
} E[MAXM+10];
int main() {
SF("%d%d", &n, &m);
for(int i = 1; i <= n; i++) fa[i] = i;
for(int i = 1; i <= m; i++) SF("%d%d%d%d", &E[i].u, &E[i].v, &E[i].a, &E[i].b);
sort(E+1, E+1+m);
for(int i = 1; i <= m; i++) {
sp.val[n+i] = E[i].b;
sp.MAX[n+i] = n+i;
}
for(int i = 1; i <= m; i++) {
int u = E[i].u, v = E[i].v, wt = E[i].b;
int x = find(u), y = find(v);
if(x != y) {
fa[x] = y;
sp.link(u, n+i); sp.link(v, n+i);
}
else {
int t = sp.query(u, v);
if(wt < sp.val[t]) {
sp.cut(E[t-n].u, t); sp.cut(E[t-n].v, t);
sp.link(u, n+i); sp.link(v, n+i);
}
}
if(find(1) == find(n)) ans = min(ans, sp.val[sp.query(1, n)] + E[i].a);
}
PF("%d", ans == INF ? -1 : ans);
}