Description
有N个点,有M条边,每条边有权值为ai,bi。
现在让你求1~n任意一条路径使max(ai)+max(bi)值最小。
Sample Input
4 5
1 2 19 1
2 3 8 12
2 4 12 15
1 3 17 8
3 4 1 17
Sample Output
32
你考虑第一维就最小生成树做,然后第二问。
这道题由于它是边权,于是你要考虑重构树的思想,把边转化成一个点。
你新加入这条边构成了环的话,那你考虑删除最大的那条边。
删除其实直接把这个便所代表的点和它连接的两个点Cut就好了。
#include
#include
#include
using namespace std;
int _min(int x, int y) {return x < y ? x : y;}
struct node {
int x, y, a, b;
} a[210000];
struct trnode {
int md, f, lazy, son[2];
} t[210000];
int n, tp, temp[210000], s[210000], fa[51000];
bool cmp(node a, node b) {return a.a < b.a;}
int findfa(int x) {
if(fa[x] != x) fa[x] = findfa(fa[x]);
return fa[x];
}
void update(int x) {
int lc = t[x].son[0], rc = t[x].son[1];
t[x].md = x;
if(s[t[lc].md] > s[t[x].md]) t[x].md = t[lc].md;
if(s[t[rc].md] > s[t[x].md]) t[x].md = t[rc].md;
}
void rotate(int x, int fx) {
int f = t[x].f, ff = t[f].f;
int r, R;
r = t[x].son[fx], R = f;
t[R].son[1 ^ fx] = r;
if(r) t[r].f = R;
r = x, R = ff;
if(t[ff].son[0] == f) t[R].son[0] = r; else if(t[ff].son[1] == f) t[R].son[1] = r;
t[r].f = R;
r = f, R = x;
t[R].son[fx] = r;
t[r].f = R;
update(f); update(x);
}
void Lazy(int x) {
if(!t[x].lazy) return ;
t[x].lazy = 0;
swap(t[x].son[0], t[x].son[1]);
int lc = t[x].son[0], rc = t[x].son[1];
if(lc) t[lc].lazy ^= 1;
if(rc) t[rc].lazy ^= 1;
}
bool hh(int x) {
int f = t[x].f;
if(f == 0 || (t[f].son[0] != x && t[f].son[1] != x)) return 0;
return 1;
}
void splay(int x) {
int i = x; tp = 0;
while(hh(i)) temp[++tp] = i, i = t[i].f;
temp[++tp] = i;
for(int i = tp; i >= 1; i--) Lazy(temp[i]);
while(hh(x)) {
int f = t[x].f, ff = t[f].f;
if(!hh(f)) {
if(t[f].son[0] == x) rotate(x, 1);
else rotate(x, 0);
}
else if(t[ff].son[0] == f && t[f].son[0] == x) rotate(f, 1), rotate(x, 1);
else if(t[ff].son[0] == f && t[f].son[1] == x) rotate(x, 0), rotate(x, 1);
else if(t[ff].son[1] == f && t[f].son[1] == x) rotate(f, 0), rotate(x, 0);
else if(t[ff].son[1] == f && t[f].son[0] == x) rotate(x, 1), rotate(x, 0);
}
}
void Access(int x) {
int y = 0;
while(x) {
splay(x);
t[x].son[1] = y;
if(y) t[y].f = x;
update(x);
y = x; x = t[x].f;
}
}
void Makert(int x) {
Access(x); splay(x);
t[x].lazy ^= 1;
}
void Link(int x, int y) {
Makert(x);
t[x].f = y;
Access(x);
}
void Cut(int x, int y) {
Makert(x);
Access(y); splay(y);
t[t[y].son[0]].f = 0; t[y].son[0] = 0;
update(y);
}
int solve(int x, int y) {
Makert(x);
Access(y); splay(y);
return t[y].md;
}
int main() {
int n, m; scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) fa[i] = i;
for(int i = 1; i <= m; i++) scanf("%d%d%d%d", &a[i].x, &a[i].y, &a[i].a, &a[i].b);
sort(a + 1, a + m + 1, cmp);
int ans = 999999999;
for(int i = 1; i <= m; i++) {
s[i + n] = a[i].b;
int fx = findfa(a[i].x), fy = findfa(a[i].y);
int x = a[i].x, y = a[i].y;
if(fx == fy) {
int dd = solve(x, y);
if(s[dd] <= a[i].b) continue;
Cut(a[dd - n].x, dd);
Cut(dd, a[dd - n].y);
}
else fa[fx] = fy;
Link(x, i + n); Link(i + n, y);
if(findfa(1) == findfa(n)) ans = _min(ans, a[i].a + s[solve(1, n)]);
}
if(ans == 999999999) printf("-1\n");
else printf("%d\n", ans);
return 0;
}