次小生成树求法:例如求最小生成树用到了 1、2、4这三条边,总共5条边,那循环3次的时候,每次分别不用1、2、4求得最小生成树的MST,最小的MST即为次小生成树

如下代码maxx即求最小生成树时求得的最大边

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cassert>
#include<iomanip>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pi acos(-1)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const double g=10.0,eps=1e-;
const int N=+,maxn=,inf=0x3f3f3f; int c[N][N],d[N],n;
bool used[N][N];//the MST i to j max power
int maxx[N][N];//the MST max power
int pre[N];//before edge
int prim()
{
bool vis[N];
memset(vis,,sizeof vis);
memset(used,,sizeof used);
memset(maxx,,sizeof maxx);
for(int i=;i<=n;i++)//the first time used 1
{
d[i]=c[][i];
pre[i]=;
}
d[]=;
pre[]=;
vis[]=;
int ans=;
for(int i=;i<=n;i++)
{
int mind=inf,k;
for(int j=;j<=n;j++)
{
if(!vis[j]&&mind>d[j])
{
mind=d[j];//find the next point that have min value with now
k=j;
}
}
if(mind==inf)return -;//not found exit
ans+=mind;
vis[k]=;
used[k][pre[k]]=used[pre[k]][k]=;
for(int j=;j<=n;j++)
{
if(vis[j])maxx[j][k]=maxx[k][j]=max(maxx[j][pre[k]],d[k]);
if(!vis[j]&&d[j]>c[j][k])
{
d[j]=c[j][k];
pre[j]=k;
}
}
}
return ans;
}
int smst(int mst)
{
int ans=inf;
for(int i=;i<=n;i++)
{
for(int j=i+;j<=n;j++)
{
if(c[i][j]!=inf&&!used[i][j])
ans=min(ans,mst+c[i][j]-maxx[i][j]);
}
}
if(ans==inf)return -;
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie();
int t,m;
cin>>t;
while(t--){
cin>>n>>m;
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
{
if(i==j)c[i][j]=;
else c[i][j]=inf;
}
}
for(int i=;i<m;i++)
{
int x,y,z;
cin>>x>>y>>z;
c[x][y]=c[y][x]=z;
}
int ans=prim();
if(ans==-)cout<<"Not Unique!"<<endl;
else
{
if(smst(ans)!=ans)cout<<ans<<endl;
else cout<<"Not Unique!"<<endl;
}
}
return ;
}

SMST

05-11 22:03