☆ [NOI2014] 魔法森林 「LCT动态维护最小生成树」
2018-10-01 20:23
344 查看
题目类型:\(LCT\)动态维护最小生成树
传送门:>Here<
题意:带权无向图,每条边有权值\(a[i],b[i]\)。要求一条从\(1\)到\(N\)的路径,使得这条路径上的\(Max\{a[i]\}+Max\{b[i]\}\)最小
解题思路
\(LCT\)板子打错调试了半个小时……菜到不能再菜了……
首先我们发现题目要求不是最小的和,而是最小的\(Max\{a[i]\}+Max\{b[i]\}\)——都只取决于最大。因此我们可以联想,如果\(Max\{a\}\)确定了,那么余下的就是用所有权值\(a\)不超过\(Max\{a\}\)的边构建一棵以\(b\)为关键字的最小生成树。显然,这样一定能保证答案最优。
因此我们可以考虑将所有边以\(a\)为关键字从小到大排序,由于是从小到大排序的,所以\(Max\{a\}\)一定是最后加入生成树的这条边的\(a\)。余下的就是维护最小生成树了,那么直接用\(LCT\)进行动态维护就好了。如果\(1,N\)已经连通(利用\(findroot\)实现并查集),那么先\(split\),查询\(Max\{b\}\),加上目前为止最大的\(Max\{a\}\)更新答案即可。
非常巧妙~~
反思
要抓住题目所说的\(Max\)
另外,\(LCT\)的\(pushup\)中要更新三次,并且每次更新\(mx[x]\)都有可能改变,因此要用\(mx[x]\)而不是\(x\)。
Code
/*By DennyQi 2018*/ #include <cstdio> #include <queue> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int MAXN = 50010; const int MAXM = 100010; const int MAXS = MAXN + MAXM; const int INF = 1061109567; inline int Max(const int a, const int b){ return (a > b) ? a : b; } inline int Min(const int a, const int b){ return (a < b) ? a : b; } inline int read(){ int x = 0; int w = 1; register char c = getchar(); for(; c ^ '-' && (c < '0' || c > '9'); c = getchar()); if(c == '-') w = -1, c = getchar(); for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w; } struct Edge{ int x,y,a,b; }e[MAXM]; int N,M,ans(INF),maxa; int val[MAXS],mx[MAXS]; struct LinkCutTree{ int ch[MAXS][2],fa[MAXS]; bool tag[MAXS]; inline bool rson(int f, int x){ return ch[f][1] == x; } inline bool isroot(int x){ return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x; } inline void pushup(int x){ mx[x] = x; if(val[mx[ch[x][0]]] > val[mx[x]]) mx[x] = mx[ch[x][0]]; if(val[mx[ch[x][1]]] > val[mx[x]]) mx[x] = mx[ch[x][1]]; } inline void rotate(int x){ int f = fa[x], gf = fa[f]; bool p = rson(f,x), q = !p; if(!isroot(f)) ch[gf][rson(gf,f)] = x; fa[x] = gf; ch[f][p] = ch[x][q], fa[ch[x][q]] = f; ch[x][q] = f, fa[f] = x; pushup(f), pushup(x); } void reverse(int x){ if(!isroot(x)) reverse(fa[x]); if(!tag[x]) return; tag[x] = 0; swap(ch[x][0], ch[x][1]); tag[ch[x][0]] ^= 1, tag[ch[x][1]] ^= 1; } inline void splay(int x){ for(reverse(x); !isroot(x); rotate(x)){ if(isroot(fa[x])){ rotate(x); break; } if(rson(fa[fa[x]],fa[x]) ^ rson(fa[x],x)) rotate(x); else rotate(fa[x]); } } inline void access(int x){ for(int y = 0; x; y=x, x = fa[x]) splay(x), ch[x][1] = y, pushup(x); } inline void mroot(int x){ access(x), splay(x), tag[x] ^= 1; } inline int findroot(int x){ access(x), splay(x); while(ch[x][0]) x = ch[x][0]; return x; } inline void split(int x, int y){ mroot(x); access(y); splay(y); } inline void link(int x, int y){ mroot(x); fa[x] = y; } inline void cut(int x, int y){ split(x,y); if(ch[y][0] != x || ch[x][1]) return; ch[y][0] = fa[x] = 0; } }qxz; inline bool cmp(const Edge& a, const Edge& b){ return a.a < b.a; } int main(){ // freopen(".in","r",stdin); N = read(), M = read(); for(int i = 1; i <= M; ++i){ e[i].x = read(), e[i].y = read(), e[i].a = read(), e[i].b = read(); } sort(e+1, e+M+1, cmp); for(int i = 1; i <= M; ++i){ val[N+i] = e[i].b; if(qxz.findroot(e[i].x) != qxz.findroot(e[i].y)){ qxz.link(e[i].x, N+i); qxz.link(e[i].y, N+i); maxa = e[i].a; } else{ qxz.split(e[i].x, e[i].y); if(val[mx[e[i].y]] > e[i].b){ int temp = mx[e[i].y]-N; qxz.cut(e[temp].x, temp+N); qxz.cut(e[temp].y, temp+N); qxz.link(e[i].x, N+i); qxz.link(e[i].y, N+i); maxa = e[i].a; } } if(qxz.findroot(1) == qxz.findroot(N)){ qxz.split(1, N); ans = Min(ans, maxa + val[mx ]); } } if(ans == INF) printf("-1"); else printf("%d", ans); return 0; }
相关文章推荐
- 【BZOJ 3669】 [Noi2014]魔法森林 LCT维护动态最小生成树
- BZOJ3669(NOI2014):魔法森林 (LCT维护最小生成树)
- 【LCT维护生成树】BZOJ3669 [Noi2014]魔法森林
- 3669 [Noi2014]魔法森林(LCT,最小生成树)
- [BZOJ3669]NOI2014魔法森林|LCT|最小生成树
- 【BZOJ3669】[Noi2014]魔法森林【Link-Cut Tree】【最小生成树】
- NKOJ 2991 (NOI 2014) 魔法森林 (动态树+最小生成树)
- 【NOI2014T2】魔法森林-LCT维护最小生成树
- NOI2014 魔法森林 LCT维护MST
- 【BZOJ 3669】 3669: [Noi2014]魔法森林 (动态spfa)
- 【BZOJ3669】【NOI2014】魔法森林 (spfa动态队列加点算法)
- 【BZOJ3669】[Noi2014]魔法森林 LCT
- 【LCT】BZOJ 3669: [Noi2014]魔法森林
- LCT——BZOJ3669/Luogu2387 [Noi2014]魔法森林
- 【BZOJ】3669: [Noi2014]魔法森林(lct+特殊的技巧)
- NOI 2014 魔法森林 LCT
- 【jzoj3754】【NOI2014】【魔法森林】【lct】
- 【bzoj3669】[Noi2014]魔法森林 LCT
- bzoj3669: [Noi2014]魔法森林 lct
- BZOJ 3669: [Noi2014]魔法森林 [LCT Kruskal | SPFA]