第一个部分 前4题 次小生成树

算法:首先如果生成了最小生成树,那么这些树上的所有的边都进行标记。标记为树边。

接下来进行枚举,枚举任意一条不在MST上的边,如果加入这条边,那么肯定会在这棵树上形成一个环,如果还要维护处树的特点

那么就要在这个环上删去一条边,这样他还是树,删掉的边显然是这条链上权值最大边更可能形成次小生成树。那么就有2中方法可以做。

第一种PRIM在prim时候直接可以做出这个从I到J的链上权值最大的值MAX[i][j];

同时可以用kruskal同样方式标记树边,然后DFS跑出MAX[i][j]

其中prim适合稠密图,kruskal适合稀疏图

2份模板

第一份:prim

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 210;
const int INF = 0x3f3f3f3f;
bool vis[MAXN];
int cost[MAXN][MAXN];
int lowcost[MAXN];
int pre[MAXN],MAX[MAXN][MAXN];
bool used[MAXN][MAXN];

int prim(int cost[][MAXN],int n)
{
    int ret = 0;
    memset(vis,false,sizeof(vis));
    memset(MAX,0,sizeof(MAX));
    memset(used,false,sizeof(used));
    vis[1] = true;
    pre[1] = -1;
    for (int i = 1 ; i <= n ; i++)
    {
        lowcost[i] = cost[1][i];
        pre[i] = 1;
    }
    lowcost[1] = 0;
    pre[1] = -1;
    for (int i = 2 ; i <= n ; i++)
    {
        int mincost = INF;
        int pos = -1;
        for (int j = 1 ; j <= n ; j++)
        {
            if (!vis[j] && lowcost[j] < mincost)
            {
                mincost = lowcost[j];
                pos = j;
            }
        }
        if (pos == -1) return -1;
        ret += mincost;
        vis[pos] = true;
        used[pos][pre[pos]] = used[pre[pos]][pos] = true;
        for (int j = 1;  j <= n ; j++)
        {
            if (vis[j] && j != pos) MAX[j][pos] = MAX[pos][j] = max(MAX[j][pre[pos]],lowcost[pos]);
            if (!vis[j] && lowcost[j] > cost[pos][j])
            {
                lowcost[j] = cost[pos][j];
                pre[j] = pos;
            }
        }
    }
    return ret;
}

int calcusmst(int cost[][MAXN],int n,int mst)
{
    int MIN = INF;
    for (int i = 1 ; i <= n ; i++)
    {
        for (int j = i + 1 ; j <= n ; j++)
        {
            if (cost[i][j] < INF && !used[i][j])
            {
                if (MIN > mst + cost[i][j] - MAX[i][j])
                    MIN = mst + cost[i][j] - MAX[i][j];
            }
        }
    }
    return MIN;
}

int main()
{
   // freopen("sample.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while (T--)
    {
        int N,M;
        scanf("%d%d",&N,&M);
        for (int i = 0 ; i <= N ; i++)
            for (int j = 0 ; j <= N ; j++) cost[i][j] = i == j ? 0 : INF;
        while (M--)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            cost[u][v] = w;
            cost[v][u] = w;
        }
        int ret = prim(cost,N);
        int smst = calcusmst(cost,N,ret);
        printf("%d %d\n",ret,smst);
    }
    return 0;
}
View Code

相关文章:

  • 2022-02-26
  • 2021-11-12
  • 2022-12-23
  • 2021-06-11
  • 2021-06-06
  • 2021-07-25
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2018-10-24
  • 2022-12-23
  • 2021-10-29
  • 2021-07-23
  • 2021-11-12
  • 2022-12-23
  • 2022-01-02
相关资源
相似解决方案