NOI 2014魔法森林
2015-01-26 17:32
309 查看
解法大致同BZOJ2594
首先先将a排序,逐边加入,每次维护一条链上最大的b,再次加入时,如果没有连通则直接链上,否则必定会生成环,那么就将b最大的删去即可
首先先将a排序,逐边加入,每次维护一条链上最大的b,再次加入时,如果没有连通则直接链上,否则必定会生成环,那么就将b最大的删去即可
#include <cstdio> #include <algorithm> using namespace std; const int MAXN = 50001; const int MAXM = 100001; const int INF = 1000001; void READ(int &x) { x = 0; char c; do c = getchar();while (c > '9' || c < '0'); do x = x*10+c-48, c = getchar(); while (c <= '9' && c >= '0'); }; struct Edge { int u,v,a,b; }; Edge Edges[MAXM]; int n,m; int f[MAXN]; bool cmpa(Edge A,Edge B) { return A.a < B.a; } struct Node *null; struct Node { int id; Node *ch[2],*f; int vA,vB; int maxA,maxB,maxBlocal; int size; bool rev; void maintain() { size = 1+ch[0]->size+ch[1]->size; maxB = vB, maxBlocal = id; if (ch[0]->maxB > maxB) maxB = ch[0]->maxB, maxBlocal = ch[0]->maxBlocal; if (ch[1]->maxB > maxB) maxB = ch[1]->maxB, maxBlocal = ch[1]->maxBlocal; maxA = max(vA,ch[0]->maxA), maxA = max(maxA,ch[1]->maxA); } void pushdown() { if (rev) { rev ^= 1; ch[0]->rev ^= 1, ch[1]->rev ^= 1; swap(ch[0],ch[1]); } } void setc(Node *c,int d){ch[d] = c, c->f = this;} bool check(){return f != null && (f->ch[0] == this || f->ch[1] == this);} int d(){return f->ch[1] == this ? 1 : 0;} Node (int _id,int _vA,int _vB):id(_id),vA(_vA),vB(_vB){ch[0] = ch[1] = f = null, rev = false, maintain();} Node (){ch[0] = ch[1] = NULL, rev = false, size = 0, maxA = maxB = -INF;} }; Node *p[MAXN+MAXM]; void rotate(Node *p) { Node *x = p->f; x->pushdown();p->pushdown(); int d = p->d(); if (!x->check()) p->f = x->f; else x->f->setc(p,x->d()); x->setc(p->ch[d^1],d); p->setc(x,d^1); x->maintain(); } void Splay(Node *p) { p->pushdown(); while (p->check()) { Node *x = p->f; if (!x->check()) rotate(p); else x->d() == p->d() ? (rotate(x),rotate(p)) : (rotate(p),rotate(p)); } p->maintain(); } void Access(Node *p) { for (Node *q = null; p != null; p = p->f) { Splay(p); p->setc(q,1); (q = p)->maintain(); } } inline void MakeRoot(Node *p) { Access(p);Splay(p);p->rev ^= 1; } void Link(Node *p,Node *q) { MakeRoot(p);p->f = q; } void Cut(Node *p,Node *q) { MakeRoot(p); Access(q);Splay(q); p->f = q->ch[0] = null; q->maintain(); } Node* Query(Node *p,Node *q) { MakeRoot(p); Access(q);Splay(q); return q; } int find(int x) { return x == f[x] ? f[x] : f[x] = find(f[x]); } int main() { null = new Node(); READ(n);READ(m); for (int i=1;i<=m;i++) READ(Edges[i].u),READ(Edges[i].v),READ(Edges[i].a),READ(Edges[i].b); sort(Edges+1,Edges+m+1,cmpa); for (int i=1;i<=n;i++) f[i] = i; for (int i=1;i<=n+m;i++) p[i] = new Node(i,0,0); int ans = INF; for (int i=1;i<=m;i++) { int Su = find(Edges[i].u); int Sv = find(Edges[i].v); Node *temp; if (Su != Sv) { f[Su] = Sv; p[i+n]->vA = Edges[i].a, p[i+n]->vB = Edges[i].b; Link(p[Edges[i].u],p[i+n]);Link(p[Edges[i].v],p[i+n]); } else { temp = Query(p[Edges[i].u],p[Edges[i].v]); if (Edges[i].b < temp->maxB) { int point = temp->maxBlocal-n; Cut(p[point+n],p[Edges[point].u]);Cut(p[point+n],p[Edges[point].v]); p[i+n] = new Node(i+n,Edges[i].a,Edges[i].b); Link(p[i+n],p[Edges[i].u]);Link(p[i+n],p[Edges[i].v]); } } if (find(1) == find(n)) temp = Query(p[1],p ), ans = min(ans,temp->maxA+temp->maxB); } if (find(1) != find(n)) { puts("-1"); return 0; } printf("%d\n",ans); return 0; }
相关文章推荐
- BZOJ 3669 . JZOJ 3754. 【NOI2014】魔法森林
- BZOJ3669 [Noi2014]魔法森林
- [NOI2014]魔法森林|动态树
- BZOJ 3669 [Noi2014]魔法森林 | LCT
- [NOI 2014]魔法森林
- [NOI2014]魔法森林
- 【bzoj 3669】[Noi2014]魔法森林
- NOI2014 魔法森林 (动态树)
- [BZOJ3669][UOJ#3][Noi2014][LCT]魔法森林
- [NOI2014]魔法森林
- [BZOJ 3669][NOI 2014]魔法森林(Link-Cut Tree)
- [JZOJ3754]【NOI2014】魔法森林
- 【NOI2014】魔法森林
- NOI2014 魔法森林 day1t2 SPFA
- 【NOI2014】魔法森林
- NOI2014 魔法森林 LCT维护MST
- [BZOJ3669]-[Noi2014]魔法森林-LCT+并查集
- [题解]bzoj3669(NOI2014)魔法森林
- NOI 2014 魔法森林
- 3669 [Noi2014]魔法森林(LCT,最小生成树)