LGOJ4172 WC2006 pipes Secretary

Outset, this complexity of the code space \ (O (^ n-2) \) , at a marking bottleneckEdge

Because bloggers too much food, too lazy to change the marking of low complexity, so the \ (BZOJ \) data life difficult

Description

link

To a map, there border erase operation, the current seeking the path of FIG \ ((x, y) \ ) is the maximum edge weight

\ (N \ leq 10 ^ 3, m \ 10 ^ 5 \)

Or \ (BZOJ \) Edition: \ (n-\ Le ^ 10. 5, m \ LE10. 6 ^ \)

Solution

\[Begin\]

Two points clear:

1. The title to \ (LCT \) (deleted because there are operating side)

2. The question to ask is offline down, then reverse edging more to do

The question is maintained in the LCT "right side"

There is a point edge conversions:

Each split into a side of the point, even the two sides of the end (the right side is \ (E [I] .dis \) ), so that you can maintain the right point in the \ (Link \) and \ (Cut \) operating in a little bit different

as follows:

cut(e[tmp - n].from, tmp);
cut(e[tmp - n].to, tmp);
link(x[i], id[x[i]][y[i]] + n);
link(y[i], id[x[i]][y[i]] + n);

FIG given first final state, and then find a minimum spanning tree

Each operation to open up the chain, that is, \ (split \)

Then the inquiry operation, directly to the \ (s [y] \)

For the operation of changing sides

Every time plus side, will be added in a spanning tree above the ring, and then we find the largest ring on the edge \ (cut \) can

( \ (Split \) has been through the chain, so you can direct off)

Then \ (link \) on the line

\[Q.E.D\]

Code

It is not difficult to write

#include <bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm {
inline int read() {
    int res = 0, f = 1;
    char k;
    while (!isdigit(k = getchar()))
        if (k == '-')
            f = -1;
    while (isdigit(k)) res = res * 10 + k - '0', k = getchar();
    return res * f;
}
const int M = 1e6 + 10, N = 1e5 + 10;
int f[N], c[N][2], s[N], v[N], st[N], n, m, q, x[N], y[N], opt[N], fa[N], ans[N], id[2010][2010];
bool r[N];
struct node {
    int from, to, dis, vis;
    bool operator<(const node &a) const { return dis < a.dis; }
} e[M];
inline void push_up(int x) {
    s[x] = max(s[c[x][0]], max(s[c[x][1]], v[x]));
    return;
}
inline bool notroot(int x) { return c[f[x]][1] == x || c[f[x]][0] == x; }
inline void pushr(int x) {
    swap(c[x][0], c[x][1]);
    r[x] ^= 1;
    return;
}
inline void push_down(int x) {
    if (r[x]) {
        if (c[x][0])
            pushr(c[x][0]);
        if (c[x][1])
            pushr(c[x][1]);
    }
    return r[x] = 0, void();
}
inline void rotate(int tx) {
    int ty = f[tx], z = f[ty], k = (c[ty][1] == tx), w = c[tx][!k];
    if (notroot(ty))
        c[z][c[z][1] == ty] = tx;
    c[tx][!k] = ty;
    c[ty][k] = w;
    if (w)
        f[w] = ty;
    f[ty] = tx;
    f[tx] = z;
    return push_up(ty), push_up(tx);
}
inline void splay(int x) {
    int y = x, z = 0;
    st[++z] = y;
    while (notroot(y)) st[++z] = y = f[y];
    while (z) push_down(st[z--]);
    while (notroot(x)) {
        y = f[x], z = f[y];
        if (notroot(y))
            rotate((c[y][0] == x) ^ (c[z][0] == y) ? x : y);
        rotate(x);
    }
    return push_up(y);
}
inline void access(int x) {
    for (int y = 0; x; x = f[y = x]) splay(x), c[x][1] = y, push_up(x);
    return;
}
inline void makeroot(int x) {
    access(x);
    splay(x);
    pushr(x);
    return;
}
inline int findroot(int x) {
    access(x);
    splay(x);
    while (c[x][0]) push_down(x), x = c[x][0];
    splay(x);
    return x;
}
inline void split(int x, int y) {
    makeroot(x);
    access(y);
    splay(y);
    return;
}
inline void link(int x, int y) {
    makeroot(x);
    if (findroot(y) != x)
        f[x] = y;
    return;
}
inline void cut(int x, int y) {
    makeroot(x);
    if (findroot(y) == x && f[y] == x && !c[y][0])
        f[y] = c[x][1] = 0, push_up(x);
    return;
}

inline int find(int x, int val) {
    if (v[x] == val)
        return x;
    return s[c[x][0]] == val ? find(c[x][0], val) : find(c[x][1], val);
}

inline int getf(int x) { return x == fa[x] ? x : fa[x] = getf(fa[x]); }
inline void merge(int x, int y) { fa[getf(x)] = getf(y); }
inline void Kruskal() {
    for (int i = 1; i <= n; ++i) fa[i] = i;
    for (int i = 1; i <= m; ++i) {
        if (!e[i].vis && getf(e[i].from) != getf(e[i].to)) {
            merge(e[i].from, e[i].to);
            link(e[i].from, n + i);
            link(e[i].to, n + i);
        }
    }
    return;
}

signed main() {
    n = read();
    m = read();
    q = read();
    for (int i = 1; i <= m; ++i) e[i].from = read(), e[i].to = read(), e[i].dis = read();
    sort(e + 1, e + m + 1);
    for (int i = 1; i <= m; ++i) {
        id[e[i].from][e[i].to] = id[e[i].to][e[i].from] = i;
        v[n + i] = e[i].dis;
    }
    for (int i = 1; i <= q; ++i) {
        opt[i] = read();
        x[i] = read();
        y[i] = read();
        if (opt[i] == 2)
            e[id[x[i]][y[i]]].vis = 1;
    }
    Kruskal();
    int num = 0;
    for (int i = q; i >= 1; --i) {
        split(x[i], y[i]);
        if (opt[i] == 1)
            ans[++num] = s[y[i]];
        else {
            int tmp = find(y[i], s[y[i]]);
            if (v[id[x[i]][y[i]] + n] < s[y[i]]) {
                cut(e[tmp - n].from, tmp);
                cut(e[tmp - n].to, tmp);
                link(x[i], id[x[i]][y[i]] + n);
                link(y[i], id[x[i]][y[i]] + n);
            }
        }
    }
    for (int i = num; i >= 1; --i) printf("%lld\n", ans[i]);
    return 0;
}
}  // namespace yspm
signed main() { return yspm::main(); }

Guess you like

Origin www.cnblogs.com/yspm/p/12364992.html