[WC 2006]水管局长

来源:互联网 发布:新点预算软件 编辑:程序博客网 时间:2024/04/27 15:57

增量最小生成树

吐槽:

动态加减边

LCT真难调。。

注意cut的写法:

先Evert(u)

再Access(v)

splay(v)

这样u->v就是一条重链,把v的左儿子和u的父亲赋为0就可以断掉边了

二分写错了啊!!


增量最小生成树

把删边倒流成加边

恩,思路是先Kruscal,不包含删掉的边(二分)

然后再添边找环

断最大的边就好了


同类题目:NOI魔法森林




#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#define maxn 200010#define Edge(u) u + nusing namespace std;int n, m;int getint(){char ch = getchar();for ( ; ch > '9' || ch < '0'; ch = getchar());int tmp = 0;for ( ; '0' <= ch && ch <= '9'; ch = getchar())tmp = tmp * 10 + int(ch) - 48;return tmp;}struct EG{int u, v, w;bool flag;inline void read(){u = getint();v = getint();w = getint();if(u > v)swap(u, v);}void print(){printf("%d %d %d\n", u, v, w);}}G[1000010];bool cmpuv(const EG& a, const EG& b){if(a.u != b.u)return a.u < b.u;if(a.v != b.v)return a.v < b.v;return a.w < b.w;}bool cmpw(const EG& a, const EG& b){return a.w < b.w;}int Lower_bound(int u, int v){int l = 1, r = m;while(l < r){int mid = l + r >> 1;if(G[mid].u == u){   if(G[mid].v == v)return mid;if(v < G[mid].v)r = mid;else l = mid + 1;}else if(u < G[mid].u)r = mid;else l = mid + 1;}return r;}struct Question{int type, u, v;inline void read(){type = getint();u = getint();v = getint();if(u > v)swap(u, v);}}q[maxn];int p[maxn];int val[maxn], c[maxn][2], fa[maxn], pos[maxn];int L[maxn], R[maxn];const int inf = 0x7fffffff;bool rev[maxn];namespace Splay{#define l c[x][0]#define r c[x][1]int st[maxn], top;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;if(l)rev[l] ^= 1;if(r)rev[r] ^= 1;swap(l, r);}}bool isroot(int x){return c[fa[x]][0] != x && c[fa[x]][1] != x;}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);}void splay(int p){st[++ top] = p;    for(int i = p; !isroot(i); i = fa[i])    st[++ top] = fa[i];while(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;Splay::pushdown(u);}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(v);Splay::splay(v);c[v][0] = fa[t] = 0;swap(u, v);Evert(t);Access(v);Splay::splay(v);c[v][0] = fa[t] = 0;}int ask(int u, int v){Evert(u);Access(v);Splay::splay(v);//cout <<"debug: "<< u << ' ' << v << ' ' << pos[v] << ' ' << val[7] << endl;return pos[v];}}namespace Kruscal{int fa[maxn];struct Edge_{int to, next, dis;}edge[maxn << 1];int h[maxn], cnt;void add(int u, int v, int d){cnt ++;edge[cnt].to = v;edge[cnt].next = h[u];edge[cnt].dis = d;h[u] = cnt;swap(u, v);cnt ++;edge[cnt].to = v;edge[cnt].next = h[u];edge[cnt].dis = d;h[u] = cnt;}int getfa(int x){return x == fa[x] ? x : fa[x] = getfa(fa[x]);}void dfs(int u){for(int i = h[u]; i; i = edge[i].next){int v = edge[i].to;if(v == fa[u])continue;fa[v] = u;val[Edge(v)] = edge[i].dis;L[Edge(v)] = u;R[Edge(v)] = v;LCT::link(u, v, Edge(v));dfs(v);}}void work(){sort(G + 1, G + 1 + m, cmpw);for(int i = 1; i <= n; i ++)    fa[i] = i;    int C = 0;for(int i = 1; i <= m; i ++){if(G[i].flag)continue;int u = getfa(G[i].u), v = getfa(G[i].v);if(u != v){C ++;fa[u] = v;add(G[i].u, G[i].v, G[i].w);if(C == n - 1)break;}}for(int i = 0; i <= n + 1; i ++)    val[i] = -inf;fa[1] = 0;for(int i = 1; i <= 2 * n; i ++)    pos[i] = i;dfs(1);}}int ans[maxn];int main(){int Q;scanf("%d%d%d", &n, &m, &Q);for(int i = 1; i <= m; i ++)    G[i].read();sort(G + 1, G + 1 + m, cmpuv);    for(int i = 1; i <= Q; i ++){        q[i].read();        if(q[i].type == 2){            int t = Lower_bound(q[i].u, q[i].v);            p[i] = G[t].w;            G[t].flag = true;        }}Kruscal::work();for(int i = Q; i >= 1; i --){int t = LCT::ask(q[i].u, q[i].v);//if(i == 1531)cout << q[i].type;if(q[i].type == 1)ans[i] = val[t];else{if(val[t] > p[i]){LCT::cut(L[t], R[t], t);val[t] = p[i];pos[t] = t;rev[t] = c[t][0] = c[t][1] = fa[t] = 0;L[t] = q[i].u, R[t] = q[i].v;LCT::link(q[i].u, q[i].v, t);}}}for(int i = 1; i <= Q; i ++)    if(q[i].type == 1)printf("%d\n", ans[i]);return 0;}



0 0
原创粉丝点击