#define MAXN 0x3f3f3f3f
using namespace std;
//#define debug
const int N=110;
int mmp[N][N],path[N][N]; //path求得是i-j的最大边权
int dis[N],pre[N];
bool vis[N],used[N][N]; //used记录是否在最小生成树中。
int n,m,mst;
inline void init(){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
mmp[i][j]=MAXN;
}
}
}
int prim(){
int mst=0;
mm(path,0);mm(vis,0);mm(used,0);
vis[1]=1;
for(int i=1;i<=n;i++){
dis[i]=mmp[1][i];
pre[i]=1;
}
int cnt=1;
while(cnt<n){
int minn=MAXN,j;
for(int i=1;i<=n;i++){
if(!vis[i]&&dis[i]<minn){
j=i;
minn=dis[i];
}
}
used[j][pre[j]]=used[pre[j]][j]=1;
mst+=mmp[pre[j]][j];
vis[j]=1;
cnt++;
for(int k=1;k<=n;k++){
if(vis[k]&&k!=j) //从k到j这条路径上最大边的权值
path[k][j]=path[j][k]=max(path[k][pre[j]],dis[j]);
if(!vis[k]&&dis[k]>mmp[j][k]){
dis[k]=mmp[j][k];
pre[k]=j;
}
}
}
return mst;
}
inline int second_tree(){
int res=MAXN;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i!=j&&!used[i][j]){
res=min(res,mst-path[i][j]+mmp[i][j]);//删除树上权值最大的路径并且加上这条路径其它边
}
}
}
return res;
}
int main()
{
#ifdef debug
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif // debug
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
int u,v,w;
init();
for(int i=0;i<m;i++){
scanf("%d%d%d",&u,&v,&w);
mmp[u][v]=w;
mmp[v][u]=w;
}
mst=prim(); //最小生成树
int smst=second_tree(); //次小生成树
}
return 0;
}
次小生成树
猜你喜欢
转载自blog.csdn.net/qq_40679299/article/details/80722128
今日推荐
周排行