[BZOJ3669][Noi2014]魔法森林 && LCT
2015-04-11 01:46
309 查看
这道题有两个权值 我们把所有边按权值a排序 剩下的边都看成点放进一个LCT中 维护每一节点的最大权值点的位置 枚举所有的边 如果u, v连通 则删去最大的边 加入这条边
否则直接加入这条边 当发现1和n连通的时候更新答案
开数组的时候把val 和 MAX开成bool也是醉了orz
否则直接加入这条边 当发现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); }
相关文章推荐
- [BZOJ3669][UOJ#3][Noi2014][LCT]魔法森林
- 【BZOJ 3669】【NOI 2014】魔法森林 LCT+枚举边
- BZOJ 3669 [Noi2014]魔法森林 | LCT
- 【LCT维护生成树】BZOJ3669 [Noi2014]魔法森林
- [bzoj3669][Noi2014]魔法森林——lct
- 【LCT】BZOJ 3669: [Noi2014]魔法森林
- [bzoj] 3669 NOI2014 魔法森林 || LCT
- BZOJ_3669_[Noi2014]魔法森林_LCT
- bzoj 3669: [Noi2014]魔法森林(并查集+LCT)
- 【BZOJ3669】[Noi2014]魔法森林 LCT
- [BZOJ3669][NOI2014]魔法森林(LCT)
- 【BZOJ 3669】 [Noi2014]魔法森林 LCT维护动态最小生成树
- [BZOJ3669][Noi2014]魔法森林(并查集+LCT)
- bzoj3669: [Noi2014]魔法森林 lct版
- [BZOJ]3669: [Noi2014]魔法森林 lct
- BZOJ 3669: [Noi2014]魔法森林 [LCT Kruskal | SPFA]
- 【BZOJ3669】【NOI2014】魔法森林 LCT
- bzoj 3669 NOI2014 魔法森林 [LCT]
- [BZOJ 3669] [Noi2014] 魔法森林 【LCT】
- 【bzoj3669】[Noi2014]魔法森林 LCT