zoukankan      html  css  js  c++  java
  • 次小生成树

    我们大部分都对最小生成树了解的多一些,一般求最小生成树的算法是prim、kurskal,那么对于次小生成树,我们也可以用上面两种算法来求解

    算法解释
    这两种算法的思路都是相同的,首先求出最小生成树,我们枚举每条不在最小生成树上的边,并把这条边放到最小生成树上面,然后就一定会形成环,那么我们在这条环路中取出一条最长的路(除了新加入的那一条边)。最终我们得到的权值就是次小生成树的权值。

    这里我采用的是kruscal求次小生成树

    不妨开一个二维数组maxd[u][v] 代表从 u 到 v的最小距离,因为kruscal求最小生成树的时候就是从最短的距离开始枚举的嘛,所以一开始枚举的肯定是最小的!

    之后我们如何去求次小生成树呢?

    首先假设ans代表最小生成树的值,并且我们把这个最小生成树的所有边都标记。然后我们去枚举未被标记的边(从小开始枚举),找到一个就进行替换  

     1 cisum = std::min(cisum,ans+e[i].w-maxd[e[i].u][e[i].v]); 

    板子题:The Unique MST

    题目连接:https://vjudge.net/problem/POJ-1679

    直接上板子吧

      1 #include <math.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <iostream>
      5 #include <algorithm>
      6 #include <string>
      7 #include <string.h>
      8 #include <vector>
      9 #include <map>
     10 #include <stack>
     11 #include <set>
     12 #include <queue>
     13 
     14 
     15 #define LL long long
     16 #define INF 0x3f3f3f3f
     17 #define ls nod<<1
     18 #define rs (nod<<1)+1
     19 const int maxn = 2e4+10;
     20 const double eps = 1e-9;
     21 std::vector<int> G[110];
     22 int maxd[110][110];
     23 
     24 int n,m,ans,cnt,cisum,fa[5050];
     25 
     26 struct node{
     27     int u, v, w;
     28     bool vis;
     29 }e[maxn];
     30 
     31 bool cmp(node a, node b)
     32 {
     33     return a.w < b.w;
     34 }
     35 
     36 int fid(int x)
     37 {
     38     return x == fa[x] ? x : fid(fa[x]);
     39 }
     40 
     41 void init(int n)
     42 {
     43     for(int i = 1; i <= n; i++) {
     44         G[i].clear();
     45         G[i].push_back(i);
     46         fa[i] = i;
     47     }
     48     ans = 0;
     49     cnt = 0;
     50 }
     51 
     52 void kruskal()
     53 {
     54     std::sort(e+1, e+m+1, cmp);
     55     for(int i = 1; i <= m; i++) {
     56         int eu = fid(e[i].u);
     57         int ev = fid(e[i].v);
     58         if(eu == ev) {
     59             continue;
     60         }
     61         ans += e[i].w;
     62         e[i].vis = true;
     63         int len_eu = G[eu].size();
     64         int len_ev = G[ev].size();
     65         for (int j=0;j<len_eu;j++) {
     66             for (int k=0;k<len_ev;k++) {
     67                 maxd[G[eu][j]][G[ev][k]] = maxd[G[ev][k]][G[eu][j]] = e[i].w;
     68             }
     69         }
     70         fa[ev] = eu;
     71         for (int j=0;j<len_ev;j++) {
     72             G[eu].push_back(G[ev][j]);
     73         }
     74         if(++cnt == n-1) {
     75             break;
     76         }
     77     }
     78     cisum = INF;
     79     for (int i=1;i<=m;i++) {
     80         if (!e[i].vis) {
     81             cisum = std::min(cisum,ans+e[i].w-maxd[e[i].u][e[i].v]);
     82         }
     83     }
     84 }
     85 
     86 int main() {
     87     int T;
     88     scanf("%d",&T);
     89     while (T--) {
     90         scanf("%d%d",&n,&m);
     91         for (int i=1;i<=m;i++) {
     92             scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
     93             e[i].vis = false;
     94         }
     95         init(n);
     96         kruskal();
     97         if (cisum>ans)
     98             printf("%d
    ",ans);
     99         else
    100             printf("Not Unique!
    ");
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    没想到吧?这货比 open 更适合读取文件
    卸载 PyCharm!这才是 Python 小白的最理想的 IDE
    git 会保留所有的提交吗?不会!
    C# 在构造函数内调用虚方法
    【转】第一个汇编器是怎么实现的
    SQL Server查询数据库所有表名与表说明
    Vue实现节流,防止重复提交
    mysql 查询json数组(一)
    VScode怎么在代码折叠后,插入新的内容
    Vue 通过调用百度API获取地理位置-经度纬度省份城市
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/11893083.html
Copyright © 2011-2022 走看看