Prim的:
#include<bits/stdc++.h>
#define ll int
#define endl '\n'
#define mem(a) memset(a,0,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const int maxn=1005;
ll dis[maxn][maxn];
ll used[maxn][maxn];ll pre[maxn];ll Max[maxn][maxn];ll vis[maxn];
ll lowcost[maxn];
ll n,m;
ll prim(ll x){
int sum=0;vis[x]=1;pre[x]=-1;
for(int i=1;i<=n;i++){
lowcost[i]=dis[x][i];
pre[i]=x;
}
for(int i=1;i<n;i++){
int mind=INF,minid=0;
for(int j=1;j<=n;j++){
if(!vis[j]&&mind>lowcost[j]){
mind=lowcost[j];
minid=j;
}
}
if(mind==INF) return -1;
sum+=mind;
vis[minid]=1;
used[minid][pre[minid]]=used[pre[minid]][minid]=1;
for(int j=1;j<=n;j++){
if(vis[j]&&j!=minid) Max[j][minid]=Max[minid][j]=max(Max[j][pre[minid]],lowcost[minid]);
if(!vis[j]&&lowcost[j]>dis[minid][j]){
lowcost[j]=dis[minid][j];
pre[j]=minid;
}
}
}
return sum;
}
int SP(int MST){
int ans=INF;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(!used[i][j]&&dis[i][j]!=INF) ans=min(ans,MST-Max[i][j]+dis[i][j]);
}
}
return ans;
}
int main(){
cin>>n>>m;
for(ll i=1;i<=n;i++){
for(ll j=1;j<=n;j++){
dis[i][j]=INF;
}
}
ll u,v,w;
for(ll i=1;i<=m;i++){
cin>>u>>v>>w;
if(w<dis[u][v]) dis[u][v]=dis[v][u]=w;
}
ll MST=prim(1);
int S_M=SP(MST);
cout<<S_M<<endl;
}
/*
5 5
1 2 5
2 3 1
3 4 2
2 4 3
4 5 5
*/
Kruskal的:
#include<bits/stdc++.h>
#define ll int
#define endl '\n'
using namespace std;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const int maxn=1005;
ll n,m,fa[maxn];
vector<int> G[maxn];
int Max[maxn][maxn];
struct node{
ll u,v,w;
bool vis;
}edge[maxn<<2];
bool cmp(node a,node b){
return a.w<b.w;
}
inline ll find(ll x){
while(x!=fa[x]) x=fa[x]=fa[fa[x]];
return x;
}
int Kruskal(){
ll eu,ev,cnt,ans=0;;
sort(edge+1,edge+m+1,cmp);
for(int i=1;i<=n;i++){
G[i].clear();
G[i].push_back(i);
}
for(ll i=1;i<=m;i++){
eu=find(edge[i].u),ev=find(edge[i].v);
if(eu==ev) continue;
edge[i].vis=true;
ans+=edge[i].w;
for(int j=0;j<G[eu].size();j++){
for(int k=0;k<G[ev].size();k++){
Max[G[eu][j]][G[ev][k]]=Max[G[ev][k]][G[eu][j]]=edge[i].w;
}
}
fa[ev]=eu;
for(int j=0;j<G[eu].size();j++){
G[ev].push_back(G[eu][j]);
}
if(++cnt==n-1) break;
}
return ans;
}
int S_K(int MST){
int ans=INF;
for(int i=1;i<=m;i++){
if(!edge[i].vis) ans=min(ans,MST+edge[i].w-Max[edge[i].u][edge[i].v]);
}
return ans;
}
int main(){
cin>>n>>m;
for(ll i=1;i<=n;i++) fa[i]=i;
for(ll i=1;i<=m;i++) {cin>>edge[i].u>>edge[i].v>>edge[i].w;edge[i].vis=false;}
int MST=Kruskal();
int S_M=S_K(MST);
cout<<S_M<<endl;
}
/*
5 5
1 2 5
2 3 1
3 4 2
2 4 3
4 5 5
*/
对于prim算法的,我每次更新的是Max[i][j],即是i到j这一段里面最大的一段长度。因为要凑环然后替换环中最大的边嘛
对于Kruskal算法,我们记录的是它的父亲节点到其的最大段距离,因为我们已经sort过了,从小到大排序,所以保障后面的一定比前面的大。