[NOI 2014]魔法森林
2016-02-18 19:26
302 查看
增量最小生成树
定一求一
定一求一
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define maxn 200010 using namespace std; int n, m; struct Edge_{ int u, v, a, b; void read(){scanf("%d%d%d%d", &u, &v, &a, &b);} bool operator<(const Edge_& k)const{ return a < k.a; } }G[maxn]; int L[maxn], R[maxn]; int val[maxn], c[maxn][2], fa[maxn], pos[maxn]; bool rev[maxn]; namespace Splay{ #define l c[x][0] #define r c[x][1] int st[maxn], top; void init(){ memset(val, 0x80, sizeof val); for(int i = 1; i <= 2 * n; i ++) pos[i] = i; } void pushup(int x){ pos[x] = x; if(val[pos[x]] < val[pos[l]]) pos[x] = pos[l]; if(val[pos[x]] < val[pos[r]]) pos[x] = pos[r]; } void pushdown(int x){ if(rev[x]){ rev[x] = 0; rev[l] ^= 1; rev[r] ^= 1; swap(l, r); } } void rotate(int p, int x){ int mark = p == c[x][1], y = c[p][mark ^ 1]; int z = fa[x]; if(x == c[z][0])c[z][0] = p; if(x == c[z][1])c[z][1] = p; if(y)fa[y] = x; fa[p] = z; c[p][mark ^ 1] = x; fa[x] = p; c[x][mark] = y; pushup(x); } bool isroot(int p){ return c[fa[p]][0] != p && c[fa[p]][1] != p; } void splay(int p){ st[top = 1] = p; for(int i = p; !isroot(i); i = fa[i]) st[++ top] = fa[i]; for(;top; top --) pushdown(st[top]); while(!isroot(p)){ int x = fa[p], y = fa[x]; if(isroot(x))rotate(p, x); else if(p == c[x][0] ^ x == c[y][0]) rotate(p, x), rotate(p, y); else rotate(x, y), rotate(p, x); } pushup(p); } #undef l #undef r } namespace LCT{ void Access(int u){ int t = 0; while(u){ Splay::splay(u); c[u][1] = t; t = u; u = fa[u]; } } void Evert(int u){ Access(u); Splay::splay(u); rev[u] ^= 1; } void link(int u, int v, int t){ Evert(v); fa[v] = t; Evert(t); fa[t] = u; } void cut(int u, int v, int t){ Evert(t); Access(u); Splay::splay(u); c[u][0] = fa[t] = 0; Evert(t); Access(v); Splay::splay(v); c[v][0] = fa[t] = 0; } int find(int u){ Access(u); Splay::splay(u); while(c[u][0])u = c[u][0]; return u; } int ask(int u, int v){ if(find(u) != find(v)) return -1; Evert(u); Access(v); Splay::splay(v); return pos[v]; } } int main(){ freopen("magicalforest.in","r",stdin); freopen("magicalforest.out","w",stdout); scanf("%d%d", &n, &m); for(int i = 1; i <= m; i ++) G[i].read(); sort(G + 1, G + 1 + m); Splay::init(); int ans = 0x7fffffff; int cnt = n; for(int i = 1; i <= m; i ++){ int t = LCT::ask(G[i].u, G[i].v); if(t == -1){ t = ++ cnt; L[t] = G[i].u; R[t] = G[i].v; val[t] = G[i].b; fa[t] = c[t][0] = c[t][1] = 0; pos[t] = t; LCT::link(L[t], R[t], t); } else if(val[t] > G[i].b){ LCT::cut(L[t], R[t], t); L[t] = G[i].u; R[t] = G[i].v; val[t] = G[i].b; fa[t] = c[t][0] = c[t][1] = 0; pos[t] = t; LCT::link(L[t], R[t], t); } t = LCT::ask(1, n); if(t != -1) ans = min(ans, val[t] + G[i].a); //cout << ans << ' ' << val[t] << ' ' << G[i].a << ' ' << G[i].b << endl; } if(ans > 1000000) ans = -1; printf("%d\n", ans); return 0; }
相关文章推荐
- python开发之——pip安装(windows环境下)
- css设计指南-笔记2
- JavaScript 中的Object的使用详解笔记(一)
- 复杂数据权限设计方案
- U3D内存优化之(四)
- RGBA
- 欢迎使用CSDN-markdown编辑器
- css设计指南-笔记1
- 第一个PyQt项目,一个计算器的实现
- mysql之查询
- Android应用开发异步任务与线程池
- Unity开发者的C#内存管理之三
- Boost智能指针——shared_ptr
- c/c++冒泡排序
- 安装Maven3时出现Exception in thread "main" java.lang.UnsupportedClassVersionError
- 统一协同办公平台--流程设计器
- HTTP协议
- LeetCode 137 Single Number II(只出现一次的数字 II)(*)
- 顺序表
- MySQL数据库limit分页、排序-SQL语句示例