第一个部分 前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; }