• 次小生成树


      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 const int inf=0x3f3f3f3f;
      4 typedef long long ll;
      5 const int M=300001;
      6 const int N=100001;
      7 struct node {
      8     int u, v, w, k;
      9     bool operator<(const node &b) const {
     10         return w < b.w;
     11     }
     12 }a[M];
     13 struct node1 {
     14     int to,next,w;
     15 }e[M];
     16 int n,m,mn=inf,t,head[N],f[N][20],d1[N][20],d2[N][20],deep[N];
     17 
     18 void add(int u,int v,int w){
     19     t++;
     20     e[t].to=v;
     21     e[t].w=w;
     22     e[t].next=head[u];
     23     head[u]=t;
     24 }
     25 
     26 struct Kurskal {
     27     int n, m,f[N];
     28     int find(int x) {
     29         return x == f[x] ? x : f[x] = find(f[x]);
     30     }
     31 
     32     ll kurskal() {
     33         int k = 0;
     34         ll ans=0;
     35         sort(a + 1, a + m + 1);
     36         for (int i = 1; i <= m; i++) {
     37             int x = find(a[i].u), y = find(a[i].v);
     38             if (x != y) {
     39                 ans += a[i].w;
     40                 a[i].k=1;
     41                 add(a[i].u, a[i].v, a[i].w);
     42                 add(a[i].v, a[i].u, a[i].w);
     43                 f[x] = y;
     44                 k++;
     45                 if (k == n - 1) {
     46                     break;
     47                 }
     48             }
     49         }
     50         return ans;
     51     }
     52 
     53     void init(int n, int m) {
     54         this->n = n;
     55         this->m = m;
     56         for (int i = 1; i <= n; i++) {
     57             f[i] = i;
     58         }
     59         for (int i = 1; i <= m; i++) {
     60             scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].w);
     61         }
     62     }
     63 } K;
     64 
     65 
     66 void dfs(int x,int fa) {
     67     for (int i = 1; i <= 16; i++) {
     68         if (deep[x] < (1 << i)) break;
     69         f[x][i] = f[f[x][i - 1]][i - 1];
     70         d1[x][i] = max(d1[x][i - 1], d1[f[x][i - 1]][i - 1]);
     71         if (d1[x][i - 1] == d1[f[x][i - 1]][i - 1]) {
     72             d2[x][i] = max(d2[x][i - 1], d2[f[x][i - 1]][i - 1]);
     73         } else {
     74             d2[x][i] = min(d1[x][i - 1], d1[f[x][i - 1]][i - 1]);
     75             d2[x][i] = max(d2[x][i - 1], d2[x][i]);
     76             d2[x][i] = max(d2[x][i], d2[f[x][i - 1]][i - 1]);
     77         }
     78     }
     79     for (int i = head[x]; i; i = e[i].next) {
     80         int to = e[i].to;
     81         if (to != fa) {
     82             f[to][0] = x;
     83             d1[to][0] = e[i].w;
     84             deep[to] = deep[x] + 1;
     85             dfs(to, x);
     86         }
     87     }
     88 }
     89 
     90 
     91 int lca(int x,int y) {
     92     if (deep[x] < deep[y]) {
     93         swap(x, y);
     94     }
     95     int h = deep[x] - deep[y], k = 0;
     96     while (h) {
     97         if (h & 1) {
     98             x = f[x][k];
     99         }
    100         h >>= 1;
    101         k++;
    102     }
    103     if (x == y) {
    104         return x;
    105     }
    106     for (int k = 19; k >= 0; k--) {
    107         if (f[x][k] != f[y][k]) {
    108             x = f[x][k];
    109             y = f[y][k];
    110         }
    111     }
    112     return f[x][0];
    113 }
    114 
    115 
    116 void cal(int x,int fa,int v) {
    117     int mx1 = 0,mx2 = 0;
    118     int h = deep[x] - deep[fa];
    119     for (int i = 0; i <= 16; i++) {
    120         if (h & (1 << i)) {
    121             if (d1[x][i] > mx1) {
    122                 mx2 = mx1;
    123                 mx1 = d1[x][i];
    124             }
    125             mx2 = max(mx2, d2[x][i]);
    126             x = f[x][i];
    127         }
    128     }
    129     if (mx1 != v) {
    130         mn = min(mn, v - mx1);
    131     } else {
    132         mn = min(mn, v - mx2);
    133     }
    134 }
    135 
    136 void solve(int i,int v){
    137     int x=a[i].u,y=a[i].v,f=lca(x,y);
    138     cal(x,f,v);
    139     cal(y,f,v);
    140 }
    141 
    142 int main() {
    143     scanf("%d%d", &n, &m);
    144     K.init(n,m);
    145     ll ans = K.kurskal();
    146     dfs(1, 0);
    147     for (int i = 1; i <= m; i++) {
    148         if (!a[i].k) {
    149             solve(i, a[i].w);
    150         }
    151     }
    152     printf("%lld
    ", ans + mn);
    153     return 0;
    154 }
    View Code
    #include<bits/stdc++.h>
    
    次小生成树
    求最小生成树时用数组Max[i][j]来表示MST中i到j最大边权
    求完后直接枚举所有不在MST中的边,替换掉最大边权的边,更新答案
    
    int prim(int cost[][maxn],int n) {
        int ans = 0;
        memset(vis, 0, sizeof(vis));
        memset(Max, 0, sizeof(Max));
        memset(used, 0, sizeof(used));
        v[0] = 1;
        pre[0] = -1;
        for (int i = 1; i <= n; i++) {
            lowc[i] = cost[0][i];
            pre[i] = 0;
        }
        lowc[0] = 0;
        for (int i = 1; i < n; i++) {
            int minc = inf;
            int p = -1;
            for (int j = 0; j < n; j++) {
                if (!vis[j] && minc > lowc[j]) {
                    minc = lowc[j];
                    p = j;
                }
            }
            if (minc == inf) {
                return -1;
            }
            ans += minc;
            vis[p] = 1;
            used[p][pre[p]] = used[pre[p]][p] = 1;
            for (int j = 0; j < n; j++) {
                if (vis[j] && j != p) {
                    Max[j][p] = Max[p][j] = max(Max[j][pre[p]], lowc[p]);
                }
                if (!vis[j] && lowc[j] > cost[p][j]) {
                    lowc[j] = cost[p][j];
                    pre[j] = p;
                }
            }
        }
        return ans;
    }
            
        }
    }
    

      

  • 相关阅读:
    电子发票 不及格的程序员
    .Net使用HttpClient以multipart/formdata形式post上传文件及其相关参数 不及格的程序员
    android开发如何获取res/raw和assets文件夹的路径 不及格的程序员
    WCF大文件上传 不及格的程序员
    Entity Framework 小技巧五 —— 如何得到EF查询生成的SQL? 不及格的程序员
    微信小程序利用云函数获取手机号码(...运算符) 不及格的程序员
    iOS开发之蓝牙/Socket链接小票打印机 不及格的程序员
    XSLT,for(int i=0;i++) 不及格的程序员
    Android 优雅的为RecyclerView添加HeaderView和FooterView 不及格的程序员
    showModalDialog, 传递window 不及格的程序员
  • 原文地址:https://www.cnblogs.com/Accpted/p/11233130.html
Copyright © 2020-2023  润新知