bzoj2594水管局长数据加强版题解
2015-08-14 18:00
369 查看
题目大意
给一张带权无向图,无重边和自环,有如下操作:
删除某条边,保证这条边在删除前一定存在,并且不破坏原图连通性;
询问两点之间所有路径中最小权值的最大值是多少;
题解
问题的答案显然在原图的最小生成树上,于是本题就变成了动态维护删边最小生成树。
然而LinkCutTree维护最小生成树时并不支持删边操作,所以要离线处理,先删掉该删掉的边,再求最小生成树,把所有操作倒过来用LCT维护。
把每条边视为一个点,编号为n+1,n+2,⋯,n+mn+1,n+2,\cdots ,n+m,权值为其边权,初始化边权最大值为自己的边权;
把原图中每个点的权值设成0;
LCT要维护每个点的编号、权值和每条实链上权值最大的点;
求最小生成树,每添一条边时,设这条边连接x和y,这条边编号为k。直接把x和k连起来,y和k也连起来。
若查询x到y路径上的最大边权,只需要把x置为根,对y进行access操作,和splay操作,返回y所在实链上权值最大的点即可。LCT上权值不为0的点一定是原图中的边。
每添一条边,查询这条边所连的两个结点路径上权值最大的边,若当前最大边的边权比新加入的还大,则断开当前最大边,把新边加入LCT中。
Code
给一张带权无向图,无重边和自环,有如下操作:
删除某条边,保证这条边在删除前一定存在,并且不破坏原图连通性;
询问两点之间所有路径中最小权值的最大值是多少;
题解
问题的答案显然在原图的最小生成树上,于是本题就变成了动态维护删边最小生成树。
然而LinkCutTree维护最小生成树时并不支持删边操作,所以要离线处理,先删掉该删掉的边,再求最小生成树,把所有操作倒过来用LCT维护。
如何用LCT维护动态添边最小生成树
设原图中有n个点,m条边;把每条边视为一个点,编号为n+1,n+2,⋯,n+mn+1,n+2,\cdots ,n+m,权值为其边权,初始化边权最大值为自己的边权;
把原图中每个点的权值设成0;
LCT要维护每个点的编号、权值和每条实链上权值最大的点;
求最小生成树,每添一条边时,设这条边连接x和y,这条边编号为k。直接把x和k连起来,y和k也连起来。
若查询x到y路径上的最大边权,只需要把x置为根,对y进行access操作,和splay操作,返回y所在实链上权值最大的点即可。LCT上权值不为0的点一定是原图中的边。
每添一条边,查询这条边所连的两个结点路径上权值最大的边,若当前最大边的边权比新加入的还大,则断开当前最大边,把新边加入LCT中。
Code
#include <cstdio> #include <algorithm> #include <cstring> #define maxn 100005 #define maxm 1000005 #define nil T[0] using namespace std; int n, m, q; struct edge { bool del; int id, x, y, w; edge(bool del = false, int id = 0, int x = 0, int y = 0, int w = 0) : id(id), x(x), y(y), w(w) {} }E[maxm]; bool cmpw(const edge &a, const edge &b) { return a.w < b.w; } bool cmpdic(const edge &a, const edge &b) { return a.x < b.x || (a.x == b.x && a.y < b.y); } bool cmpid(const edge &a, const edge &b) { return a.id < b.id; } struct node *T[maxm + maxn + maxn], *S[maxm + maxn + maxn]; struct node { bool rev; int id, val; node *fa, *lc, *rc, *mx; node(bool rev = false, int id = 0, int val = 0, node *fa = nil, node *lc = nil, node *rc = nil, node *mx = nil) : rev(rev), id(id), val(val), fa(fa), lc(lc), rc(rc), mx(mx) {} inline void update() { mx = this; if(lc -> mx -> val > mx -> val) mx = lc -> mx; if(rc -> mx -> val > mx -> val) mx = rc -> mx; } inline void pushdown() { if(rev) { rev = false; lc -> rev ^= 1; rc -> rev ^= 1; swap(lc, rc); } } }; void zig(node *x) { node *y = x -> fa; y -> lc = x -> rc; x -> rc -> fa = y; x -> rc = y; x -> fa = y -> fa; if(y == y -> fa -> lc) y -> fa -> lc = x; else if(y == y -> fa -> rc) y -> fa -> rc = x; y -> fa = x; y -> update(); } void zag(node *x) { node *y = x -> fa; y -> rc = x -> lc; x -> lc -> fa = y; x -> lc = y; x -> fa = y -> fa; if(y == y -> fa -> lc) y -> fa -> lc = x; else if(y == y -> fa -> rc) y -> fa -> rc = x; y -> fa = x; y -> update(); } void splay(node *x) { int top = 0; S[top++] = x; for(node *i = x; i == i -> fa -> lc || i == i -> fa -> rc; i = i -> fa) { S[top++] = i -> fa; } while(top--) S[top] -> pushdown(); node *y = nil, *z = nil; while(x == x -> fa -> lc || x == x -> fa -> rc) { y = x -> fa; z = y -> fa; if(x == y -> lc) { if(y == z -> lc) zig(y); zig(x); } else { if(y == z -> rc) zag(y); zag(x); } } x -> update(); } inline void access(node *x) { for(node *y = nil; x != nil; y = x, x = x -> fa) { splay(x); x -> rc = y; x -> update(); } } inline void makeroot(node *x) { access(x); splay(x); x -> rev ^= 1; } inline void lnk(node *x, node *y) { makeroot(x); x -> fa = y; } inline void cut(node *x, node *y) { makeroot(x); access(y); splay(y); x -> fa = y -> lc = nil; y -> update(); } inline node* query(node *x, node *y) { makeroot(x); access(y); splay(y); return y -> mx; } int ufs[maxn]; inline int find(int x) { return x == ufs[x] ? x : find(ufs[x]); } int find(int x, int y) { int l = 1, r = m, mid; while(l <= r) { mid = l + r >> 1; if(E[mid].x < x || (E[mid].x == x && E[mid].y < y)) l = mid + 1; else if(E[mid].x == x && E[mid].y == y) return mid; else r = mid - 1; } } struct opt { int id, k, x, y, ans; opt(int id = 0, int k = 0, int x = 0, int y = 0, int ans = 0) : id(id), k(k), x(x), y(y), ans(ans) {} } sta[maxn]; inline void read(int &a) { char ch = getchar(); a = 0; while(ch < '0' || ch > '9') ch = getchar(); while(ch >= '0' && ch <= '9') { a = a * 10 + ch - 48; ch = getchar(); } } inline void write(int a) { int top = 0, ch[30]; do { ch[top++] = a % 10 + 48; a /= 10; } while(a > 0); while(top--) putchar(ch[top]); putchar('\n'); } void init() { #ifndef ONLINE_JUDGE freopen("2594i.txt", "r", stdin); freopen("2594o.txt", "w", stdout); #endif int a, b, c; read(n); read(m); read(q); nil = new node(); *nil = node(); for(int i = 1; i <= n + m + 100; ++i) T[i] = new node(false, i); for(int i = 1; i <= n; ++i) ufs[i] = i; for(int i = 1; i <= m; ++i) { scanf("%d%d%d", &E[i].x, &E[i].y, &E[i].w); if(E[i].x > E[i].y) swap(E[i].x, E[i].y); } sort(E + 1, E + m + 1, cmpw); for(int i = 1; i <= m; ++i) { E[i].id = i; T[n + i] -> val = E[i].w; T[n + i] -> mx = T[n + i]; } sort(E + 1, E + m + 1, cmpdic); for(int i = 1; i <= q; ++i) { read(sta[i].k); read(sta[i].x); read(sta[i].y); if(sta[i].k == 2) { if(sta[i].x > sta[i].y) swap(sta[i].x, sta[i].y); int tmp = find(sta[i].x, sta[i].y); E[tmp].del = true; sta[i].id = E[tmp].id; } } sort(E + 1, E + m + 1, cmpid); } void work() { for(int i = 1, tot = 0; i <= m && tot < n - 1; ++i) { if(!E[i].del) { int tmpu = find(E[i].x), tmpv = find(E[i].y); if(tmpu != tmpv) { ufs[tmpu] = tmpv; lnk(T[E[i].x], T[i + n]); lnk(T[E[i].y], T[i + n]); ++tot; } } } for(int i = q; i > 0; --i) { if(sta[i].k == 1) { node *p = query(T[sta[i].x], T[sta[i].y]); sta[i].ans = p -> val; } else { node *p = query(T[sta[i].x], T[sta[i].y]); if(E[sta[i].id].w < p -> val) { cut(T[E[p -> id - n].x], p); cut(T[E[p -> id - n].y], p); lnk(T[sta[i].x], T[sta[i].id + n]); lnk(T[sta[i].y], T[sta[i].id + n]); } } } for(int i = 1; i <= q; ++i) if(sta[i].k == 1) { write(sta[i].ans); } for(int i = 0; i <= n + m + 100; ++i) { delete T[i]; T[i] = NULL; } } int main() { init(); work(); return 0; }
相关文章推荐
- .nav ul .mall a:hover 是什么意思
- 解决checkbox的attr(checked)一直为undefined问题
- JLINK(SEGGER)灯不亮 USB不识别固件修复、clone修改
- C中不安全函数
- JLINK(SEGGER)灯不亮 USB不识别固件修复、clone修改
- iOS真机系列之真机调试
- jack's things
- FFmpeg常用基本命令
- Ambiguous handler methods mapped for HTTP path
- cvs常用命令
- PHP写文件——将用户提交的数据保存到服务器的文件中
- JavaScript之Window对象
- hadoop-mapreduce学习
- 怎样把网站变为灰色的代码
- java ssh三大框架搭建整合
- CHM文件为什么打开什么都没有?
- OC的Runtime(运行时)机制的解析
- POJ 1328 Radar Installation
- GPX文件格式适用于GPS定位的模拟以及生成文件
- 构造函数,你真的弄懂了吗?