zoukankan      html  css  js  c++  java
  • BZOJ 1977[BeiJing2010组队]次小生成树 Tree

    描述:

    就是求一个次小生成树的边权和

    传送门

    题解

    我们先构造一个最小生成树, 把树上的边记录下来。

    然后再枚举每条非树边(u, v, val),在树上找出u 到v 路径上的最小边$g_0$ 和 严格次小边 $g_1$

    如果$val > g_0$就可以考虑把$g_0$ 替换成$val$ 并记录答案。

    如果$val = g_0$ 就把$g_1$替换成$val$ 记录答案。

    然后我们就需要快速求出树链上的最小和次小边, 需要用树上倍增求LCA类似的方法求。

    定义$g[0][ i ][ j ]$ 表示从$j$ 到第 $2^i$ 辈祖先中的最小边, $g[1][ i ][ j ] $表示从$j$ 到 第$2^i$ 辈祖先中的次小边, 满足以下关系:

    1: $g[0][ i ][ j ] = max( g[0][ i - 1][ j ], g[0][ i - 1][ f[i - 1][ j ]]) $

    2 :$ g[1][ i ][ j ] = max( g[1][ i - 1][ j ], g[1][ i - 1 ][ f[i - 1][ j ]]) $  当$g[0][i - 1][ j ] = g[0][ i - 1][ f[i - 1][ j ]] $

    3: $ g[1][ i ][ j ] = max(g[0][ i - 1][ j ], g[1][ i - 1][ f[i - 1][ j ]])$  当$g[0][i - 1][ j ] < g[0][ i - 1][ f[i - 1][ j ]] $

    4: $ g[1][ i ][ j ] = max(g[1][ i - 1][ j ], g[0][ i - 1][ f[i - 1][ j ]])$  当$g[0][i - 1][ j ] > g[0][ i - 1][ f[i - 1][ j ]] $

    倍增求树链上的最小和次小值时同理合并

    题解

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define rd read()
      5 #define rep(i,a,b) for(register int i = (a); i <= (b); ++i)
      6 #define per(i,a,b) for(register int i = (a); i >= (b); --i)
      7 #define ll long long
      8 using namespace std;
      9 
     10 const int N = 5e5;
     11 const int inf = ~0U >> 1;
     12 
     13 int n, m;
     14 ll sum, ans = 1e18;
     15 int fa[N], f[30][N], g[2][30][N], dep[N];
     16 int head[N], tot;
     17 
     18 struct edge {
     19     int nxt, to, val;
     20 }e[N << 2];
     21 
     22 struct node {
     23     int u, v, val, mk;
     24 }E[N << 2];
     25 
     26 inline int read() {
     27     int X = 0, p = 1; char c = getchar();
     28     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
     29     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
     30     return X * p;
     31 }
     32 
     33 inline void added(int u, int v, int val) {
     34     e[++tot].to = v;
     35     e[tot].nxt = head[u];
     36     e[tot].val = val;
     37     head[u] = tot;
     38 }
     39 
     40 inline void add(int u, int v, int val) {
     41     added(u, v, val); added(v, u, val);
     42 }
     43 
     44 inline int fd(int x) {
     45     return fa[x] == x ? x : fa[x] = fd(fa[x]);
     46 }
     47 
     48 inline int cmp(const node &A, const node &B) {
     49     return A.val < B.val;
     50 }
     51 
     52 inline void dfs(int u) {
     53     for(int i = head[u]; i; i = e[i].nxt) {
     54         int nt = e[i].to;
     55         if(nt == f[0][u]) continue;
     56         f[0][nt] = u;
     57         g[0][0][nt] = e[i].val;
     58         g[1][0][nt] = -inf;
     59         dep[nt] = dep[u] + 1;
     60         dfs(nt);
     61     }
     62 }
     63 
     64 inline void LCA(int x, int y, int &a, int &b) {
     65     int g0, g1;
     66     if(dep[x] < dep[y]) swap(x, y);
     67     for(int i = 20; ~i; --i) if(dep[f[i][x]] >= dep[y]) {
     68         g0 = g[0][i][x]; g1 = g[1][i][x];
     69         if(g0 == a) b = max(b, g1);
     70         if(g0 > a) b = max(a, g1);
     71         if(g0 < a) b = max(g0, b);
     72         a = max(a, g0);
     73         x = f[i][x];
     74     }
     75     for(int i = 20; ~i; --i) if(f[i][x] != f[i][y]) {
     76         g0 = g[0][i][x]; g1 = g[1][i][x];
     77         if(g0 == a) b = max(b, g1);
     78         if(g0 > a) b = max(a, g1);
     79         if(g0 < a) b = max(g0, b);
     80         a = max(a, g0);
     81 
     82         g0 = g[0][i][y]; g1 = g[1][i][y];
     83         if(g0 == a) b = max(b, g1);
     84         if(g0 > a) b = max(a, g1);
     85         if(g0 < a) b = max(g0, b);
     86         a = max(a, g0);
     87         x = f[i][x]; y = f[i][y];
     88     }
     89 
     90     g0 = g[0][0][x]; g1 = g[1][0][x];
     91     if(g0 == a) b = max(b, g1);
     92     if(g0 > a) b = max(a, g1);
     93     if(g0 < a) b = max(g0, b);
     94     a = max(a, g0);
     95 
     96     g0 = g[0][0][y]; g1 = g[1][0][y];
     97     if(g0 == a) b = max(b, g1);
     98     if(g0 > a) b = max(a, g1);
     99     if(g0 < a) b = max(g0, b);
    100     a = max(a, g0);    
    101 }
    102 
    103 int main()
    104 {
    105     n = rd; m = rd;
    106     rep(i, 1, n) fa[i] = i;
    107     rep(i, 1, m) {
    108         int u = rd, v = rd, val = rd;
    109         E[i].u = u; E[i].v = v; E[i].val = val; E[i].mk = 0;
    110     }
    111     sort(E+1, E+1+m, cmp);
    112     rep(i, 1, m) {
    113         int x = fd(E[i].u), y = fd(E[i].v);
    114         if(x == y) continue;
    115         sum += E[i].val;
    116         fa[y] = x;
    117         E[i].mk = 1;
    118         add(E[i].u, E[i].v, E[i].val);
    119     }
    120     dep[1] = 1;
    121     dfs(1);
    122     rep(i, 1, 20) rep(j, 1, n) {
    123         f[i][j] = f[i - 1][f[i - 1][j]];
    124         g[0][i][j] = max(g[0][i - 1][j], g[0][i - 1][f[i - 1][j]]);
    125         int tmp = -inf;
    126         if(g[0][i - 1][j] == g[0][i - 1][f[i - 1][j]]) tmp = max(g[1][i - 1][j], g[1][i - 1][f[i - 1][j]]);
    127         if(g[0][i - 1][j] < g[0][i - 1][f[i - 1][j]]) tmp = max(g[0][i - 1][j], g[1][i - 1][f[i - 1][j]]);
    128         if(g[0][i - 1][j] > g[0][i - 1][f[i - 1][j]]) tmp = max(g[1][i - 1][j], g[0][i - 1][f[i - 1][j]]);
    129         g[1][i][j] = tmp;
    130     }
    131     rep(i, 1, m) if(!E[i].mk) {
    132         int x = E[i].u, y = E[i].v, g0 = -inf, g1 = -inf;
    133         LCA(x, y, g0, g1);
    134         if(E[i].val == g0 && g1 != -inf) ans = min(ans, sum + E[i].val - g1);
    135         if(E[i].val > g0) ans = min(ans, sum + E[i].val - g0);
    136     }
    137     printf("%lld
    ",ans);
    138 }
    View Code
  • 相关阅读:
    【codecombat】 试玩全攻略 第九关 循环又循环
    【codecombat】 试玩全攻略 第十三关 已知敌人
    【codecombat】 试玩全攻略 第十一关 再次迷宫经历
    【codecombat】 试玩全攻略 第六关 cell commentary
    【codecombat】 试玩全攻略 第八关 火舞
    【codecombat】 试玩全攻略 第十二关 恐惧之门
    【codecombat】 试玩全攻略 第十四关 已知敌人
    苹果apns推送总结
    Xcode 提升速度小技巧
    UITextField 限制输入字数
  • 原文地址:https://www.cnblogs.com/cychester/p/9556536.html
Copyright © 2011-2022 走看看