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

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

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 3514  Solved: 941
    [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

    【题解】

    非严格次小生成树:求得MST,枚举加哪一条边,删除环上的最大边。

    严格次小生成树:若最大边 = 加入的边,那么找不等于最大边的次大边

    很多细节,见代码

    求一条路径上最大边次大边时,用lca把他们拆成两条链求,更方便

    由于INF设小了WA了一发

    由于忘记在链上蹦跶了,WA了两发

    我的AC记录啊。。。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 #include <queue>
      7 #include <vector>
      8 #include <map>
      9 #include <string> 
     10 #include <cmath> 
     11 #define min(a, b) ((a) < (b) ? (a) : (b))
     12 #define max(a, b) ((a) > (b) ? (a) : (b))
     13 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
     14 template<class T>
     15 inline void swap(T &a, T &b)
     16 {
     17     T tmp = a;a = b;b = tmp;
     18 }
     19 inline void read(long long &x)
     20 {
     21     x = 0;char ch = getchar(), c = ch;
     22     while(ch < '0' || ch > '9') c = ch, ch = getchar();
     23     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
     24     if(c == '-') x = -x;
     25 }
     26 
     27 const long long INF = 0x3f3f3f3f3f3f3f3f;
     28 const long long MAXN = 500000 + 10;
     29 const long long MAXM = 500000 + 10;
     30 
     31 long long u[MAXM],v[MAXM],w[MAXM],cnt[MAXM],n,m,fa[MAXN],tot,f1,f2,M,vis[MAXM];
     32 long long cmp(long long a, long long b)
     33 {
     34     return w[a] < w[b];
     35 } 
     36 long long find(long long x)
     37 {
     38     return x == fa[x] ? x : fa[x] = find(fa[x]);
     39 }
     40 struct Edge
     41 {
     42     long long u,v,w,nxt;
     43     Edge(long long _u, long long _v, long long _w, long long _nxt){u = _u;v = _v;w = _w;nxt = _nxt;}
     44     Edge(){}
     45 }edge[MAXN << 1];
     46 long long head[MAXN], cntt;
     47 inline void insert(long long a, long long b, long long c)
     48 {
     49     edge[++ cntt] = Edge(a,b,c,head[a]);
     50     head[a] = cntt;
     51 } 
     52 
     53 //p[0]表示跳到哪个节点,p[1]表示最大值,p[2]表示次大值 
     54 long long p[3][30][MAXN], deep[MAXN];
     55 void dfs(long long x, long long pre)
     56 {
     57     for(long long pos = head[x];pos;pos = edge[pos].nxt)
     58     {
     59         long long v = edge[pos].v;
     60         if(v == pre) continue;
     61         p[0][0][v] = x, p[1][0][v] = edge[pos].w;deep[v] = deep[x] + 1, dfs(v, x);
     62     }
     63 }
     64 void yuchuli()
     65 {
     66     memset(p[1], -1, sizeof(p[1]));
     67     memset(p[2], -1, sizeof(p[2]));
     68     dfs(1, -1);
     69     for(M = 0;(1 << M) <= n;++ M); -- M;
     70     for(long long i = 1;i <= M;++ i) 
     71         for(long long j = 1;j <= n;++ j)
     72             p[0][i][j] = p[0][i - 1][p[0][i - 1][j]];
     73     for(long long i = 1;i <= M;++ i)
     74         for(long long j = 1;j <= n;++ j)
     75             if(deep[j] >= (1 << i)) 
     76             {
     77                 long long tmp1 = p[1][i - 1][j], tmp2 = p[1][i - 1][p[0][i - 1][j]];
     78                 if(tmp1 == tmp2) p[2][i][j] = max(p[2][i - 1][j], p[2][i - 1][p[0][i - 1][j]]), p[1][i][j] = tmp1;
     79                 else if(tmp1 > tmp2) p[2][i][j] = max(tmp2, p[2][i - 1][j]), p[1][i][j] = tmp1;
     80                 else p[2][i][j] = max(tmp1, p[2][i - 1][p[0][i - 1][j]]), p[1][i][j] = tmp2;
     81             }
     82 }
     83 long long LCA(long long u, long long v)
     84 {
     85     if(deep[u] < deep[v]) swap(u, v);
     86     for(long long i = M;i >= 0;-- i)
     87         if(deep[u] >= deep[v] + (1 << i))
     88             u = p[0][i][u];
     89     if(u == v) return u;
     90     for(long long i = M;i >= 0;-- i)
     91         if(p[0][i][u] != p[0][i][v])
     92             u = p[0][i][u], v = p[0][i][v];
     93     return p[0][0][u];
     94 }
     95 //v为lca 
     96 void lian(long long &ma, long long &cima, long long u, long long v)
     97 {
     98     ma = cima = -1;
     99     for(long long i = M;i >= 0;-- i)
    100         if(deep[u] >= deep[v] + (1 << i))
    101         {
    102             if(ma < p[1][i][u]) cima = max(ma, p[2][i][u]), ma = p[1][i][u];
    103             else if(ma > p[1][i][u]) cima = max(cima, p[1][i][u]);
    104             else cima = max(cima, p[2][i][u]);
    105             u = p[0][i][u];
    106         }
    107 }
    108 
    109 void find(long long &ma, long long &cima, long long u, long long v)
    110 {
    111     long long lca = LCA(u, v);
    112     long long lma, lcima, rma, rcima;
    113     lian(lma, lcima, u, lca), lian(rma, rcima, v, lca);
    114     ma = max(lma, rma);
    115     if(lma > rma) cima = max(rma, lcima);
    116     else if(lma < rma) cima = max(lma, rcima);
    117     else cima = max(lcima, rcima);
    118 }
    119 
    120 long long ans, ans2;
    121 int main()
    122 {
    123     read(n), read(m);
    124     for(long long i = 1;i <= m;++ i) cnt[i] = i, read(u[i]), read(v[i]), read(w[i]);
    125     for(long long i = 1;i <= n;++ i) fa[i] = i;
    126     std::sort(cnt + 1, cnt + 1 + m, cmp);
    127     for(long long i = 1;i <= m;++ i)
    128     {
    129         f1 = find(u[cnt[i]]), f2 = find(v[cnt[i]]);
    130         if(f1 == f2) continue;
    131         ++ tot;insert(u[cnt[i]], v[cnt[i]], w[cnt[i]]), insert(v[cnt[i]], u[cnt[i]], w[cnt[i]]);
    132         fa[f1] = f2; vis[cnt[i]] = 1;ans += w[cnt[i]];
    133         if(tot == n - 1) break;
    134     }
    135     yuchuli();ans2 = INF;
    136     for(long long i = 1;i <= m;++ i)
    137     {
    138         if(vis[i]) continue;
    139         long long ma,cima;
    140         find(ma, cima, u[i], v[i]);
    141         if(w[i] != ma) ans2 = min(ans2, ans + (w[i] - ma));
    142         else ans2 = min(ans2, ans + (w[i] - cima));
    143     }
    144     printf("%lld
    ", ans2);
    145     return 0;
    146 }
    BZOJ1977
  • 相关阅读:
    网站如何做404错误页面
    阿里云虚拟主机二级域名绑定二级目录以及域名重定向的用法
    301重定向的方法
    利用JavaScript做无缝滚动
    day 10
    day 9
    day 9
    day 8
    day 8
    day 7
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8377943.html
Copyright © 2011-2022 走看看