• BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )


    做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案.

    树链剖分然后ST维护最大值和严格次大值..倍增也是可以的... 

    ------------------------------------------------------------------------------

    #include<bits/stdc++.h>
     
    using namespace std;
     
    #define b(i) (1 << (i))
    typedef long long ll;
     
    const int maxn = 100009;
    const int maxm = 300009;
     
    inline int read() {
    int ret = 0;
    char c = getchar();
    for(; !isdigit(c); c = getchar());
    for(; isdigit(c); c = getchar())
       ret = ret * 10 + c - '0';
    return ret;
    }
     
    ll tot = 0;
     
    struct edge {
    int to, w;
    edge* next;
    } EDGES[maxn << 1], *pt = EDGES, *head[maxn];
     
    inline void add(int u, int v, int w) {
    pt->to = v; pt->w = w; pt->next = head[u]; head[u] = pt++;
    }
    inline void addedge(int u, int v, int w) {
    tot += w;
    add(u, v, w); add(v, u, w);
    }
     
    int w[maxn], _id[maxn], N, M;
     
    struct data {
    int mx, _mx;
    data(int _ = -1, int __ = -1):mx(_), _mx(__) {}
    };
     
    data make(int _, int __) {
    return data(_, __);
    }
     
    data update(data a, data b) {
    if(a.mx < b.mx)
       return data(b.mx, max(a.mx, b._mx));
    else if(a.mx > b.mx)
       return data(a.mx, max(b.mx, a._mx));
    else 
       return data(a.mx, max(a._mx, b._mx));
    }
     
    struct ST {
    static const int maxlog = 20;
    data mx[maxn][maxlog];
    void init() {
    for(int i = 0; i < N; i++) {
    mx[i][0].mx = w[_id[i]];
    mx[i][0]._mx = -1;
    }
    for(int i = 1; b(i) <= N; i++)
       for(int j = 0; j + b(i) <= N; j++)
        mx[j][i] = update(mx[j][i - 1], mx[j + b(i - 1)][i - 1]);
    }
    data query(int x, int y) {
    int n = 0;
    while(b(n) <= y - x + 1) n++; n--;
    return update(mx[x][n], mx[y - b(n) + 1][n]);
    }
    } st;
     
    struct SLPF {
    static const int INF = 1000000000;
    int top[maxn], size[maxn], son[maxn], dep[maxn], fa[maxn], id[maxn];
    int TOP, n;
    void dfs(int x) {
    size[x] = 1;
    son[x] = -1;
    for(edge* e = head[x]; e; e = e->next) if(fa[x] != e->to) {
    fa[e->to] = x;
    dep[e->to] = dep[x] + 1;
    w[e->to] = e->w;
    dfs(e->to);
    size[x] += size[e->to];
    if(!~son[x] || size[son[x]] < size[e->to]) son[x] = e->to;
    }
    }
    void DFS(int x) {
    top[x] = TOP;
    _id[id[x] = n++] = x;
    if(~son[x]) DFS(son[x]);
    for(edge* e = head[x]; e; e = e->next)
       if(e->to != son[x] && e->to != fa[x]) DFS(TOP = e->to);
    }
    void init() {
    dep[0] = 0; fa[0] = -1;
    dfs(0); DFS(n = 0);
    }
    data query(int x, int y) {
    data ret;
    for(; top[x] != top[y]; x = fa[top[x]]) {
    if(dep[top[x]] < dep[top[y]]) swap(x, y);
    ret = update(ret, st.query(id[top[x]], id[x]));
    }
    if(x == y) return ret;
    if(dep[x] < dep[y]) swap(x, y);
    return update(ret, st.query(id[y] + 1, id[x]));
    }
    } slpf;
     
    struct EDGE {
    int u, v, w;
    bool t;
    inline void Read() {
    u = read() - 1;
    v = read() - 1;
    w = read();
    t = false;
    }
    bool operator < (const EDGE &e) const {
    return w < e.w;
    }
    } E[maxm];
     
    struct DSU {
    int p[maxn];
    void init() {
    for(int i = 0; i < N; i++) p[i] = i;
    }
    int find(int x) {
    return x == p[x] ? x : p[x] = find(p[x]);
    }
    inline bool unite(int x, int y) {
    x = find(x); y = find(y);
    p[x] = y;
    return x != y;
    }
    } dsu;
     
    void MST() {
    sort(E, E + M);
    dsu.init();
    for(int i = 0; i < M; i++) if(dsu.unite(E[i].u, E[i].v)) {
    addedge(E[i].u, E[i].v, E[i].w);
    E[i].t = true;
    }
    }
     
    void init() {
    scanf("%d%d", &N, &M);
    for(int i = 0; i < M; i++) E[i].Read();
    }
     
    void work() {
    slpf.init(); st.init();
    ll ans = ll(1e17);
    for(int i = 0; i < M; i++) if(!E[i].t) {
    data h = slpf.query(E[i].u, E[i].v);
    if(E[i].w == h.mx) {
    if(~h._mx) ans = min(ans, tot - h._mx + E[i].w);
    } else
       ans = min(ans, tot - h.mx + E[i].w);
    }
    printf("%lld ", ans);
    }
     
    int main() {
    init();
    MST();
    work();
    return 0;
    }

    ------------------------------------------------------------------------------ 

    1977: [BeiJing2010组队]次小生成树 Tree

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 2422  Solved: 578
    [Submit][Status][Discuss]

    Description

    小 C 最近学了很多最小生成树的算法,Prim 算法、Kurskal 算法、消圈算法等等。 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了。小 P 说,让小 C 求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说: 如果最小生成树选择的边集是 EM,严格次小生成树选择的边集是 ES,那么需要满足:(value(e) 表示边 e的权值)  这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。

    Input

    第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z。

    Output

    包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)

    Sample Input

    5 6
    1 2 1
    1 3 2
    2 4 3
    3 5 4
    3 4 3
    4 5 6

    Sample Output

    11

    HINT

    数据中无向图无自环; 50% 的数据N≤2 000 M≤3 000; 80% 的数据N≤50 000 M≤100 000; 100% 的数据N≤100 000 M≤300 000 ,边权值非负且不超过 10^9 。

    Source

  • 相关阅读:
    在二进制与文本之间转换plist文件
    iOS 音频分贝的计算
    iOS 圆形水波浪效果实现
    iOS画圆、画线
    iOS IM开发准备工作(四)CocoaAsyncSocket的使用
    iOS IM开发准备工作(三)乱说Socket
    iOS IM开发准备工作(二)protobuf-objc安装及使用
    iOS IM开发准备工作(一)XML解析
    iOS IM开发blog写作计划
    西游记倒着看。。我从贴吧看来的
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4810203.html
Copyright © 2020-2023  润新知