版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Masqueradey/article/details/52648212
这道题算是对最小生成树的一个衍生,给你一个树,判断它的最小生成树是否唯一,这里需要用到次小生成树算法,如果次小生成树大小和最小生成树一样,则不唯一。
算法1(每次从最小生成树上去掉一个边,再求该图的最小生成树的权值和,再对所有新生成的最小生成树求最小值,即为次小生成树)
代码:
#include<iostream>
#include<cstring>
using namespace std;
#define maxn 2000000
int m,n,sum,flag[1005],map[1005][1005];
int mst[1005];
int prim1(int p){
int pos,t,i,j,minn,sum=0;
int low[1005];
t=map[mst[p]][p];
map[mst[p]][p]=map[p][mst[p]]=maxn;
memset(flag,0,sizeof(flag));
for(i=2;i<=n;i++){low[i]=map[1][i];}
for(i=2;i<=n;i++)
{
minn=maxn;
for(j=2;j<=n;j++)
if(!flag[j]&&low[j]<minn){minn=low[j];pos=j;}
sum+=minn;
flag[pos]=1;
for(j=2;j<=n;j++)
if(!flag[j]&&map[pos][j]<low[j]){low[j]=map[pos][j];}
}
map[mst[p]][p]=map[p][mst[p]]=t;
return sum;
}
int prim(){
int pos,minn,i,j,sum=0;
int low[1005];
memset(flag,0,sizeof(flag));
memset(mst,0,sizeof(mst));
for(i=2;i<=n;i++){low[i]=map[1][i];mst[i]=1;}
for(i=2;i<=n;i++)
{
minn=maxn;
for(j=2;j<=n;j++)
if(!flag[j]&&low[j]<minn){minn=low[j];pos=j;}
sum+=minn;
flag[pos]=1;
for(j=2;j<=n;j++)
if(!flag[j]&&map[pos][j]<low[j]){low[j]=map[pos][j];mst[j]=pos;}
}
for(i=2;i<=n;i++)
if(sum==prim1(i)){return 0;}
return sum;
}
int main(){
int i,j,x,y,z,t,ss;
cin>>t;
while(t--){
cin>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
map[i][j]=maxn;
}
for(i=1;i<=m;i++)
{
cin>>x>>y>>z;
map[x][y]=map[y][x]=z;
}
ss=prim();
if(ss!=0)cout<<ss<<endl;
else cout<<"Not Unique!"<<endl;
}
return 0;
}
算法2(在计算最小生成树时用maxx数组记录两个点形成的路径上权值最大的边,完成对最小生成树的计算之后,每次加入一个未被访问的边,此时的最小生成树一定成环,再通过maxx数组减去一个i,j之间最小生成树上权值最大的边,则得新的最小生成树权值,再遍历所有未被访问的边,得到新的最小生成树集合中的最小值,如果等于原来的最小生成树值,则不唯一)
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 2000000
int m,n;
int flag[1005];
int map[1005][1005],maxx[1005][1005],used[1005][1005];
int mst[1005];
int low[1005];
int mm(int sum){
int i,j,minn=maxn;
for(i=1;i<=n;i++)
for(j=i+1;j<=n;j++)
if(!used[i][j]&&map[i][j]<maxn)
minn=min(minn,sum+map[i][j]-maxx[i][j]);
if(minn==sum)return 1;
return 0;
}
int prim(){
int pos,minn,i,j,sum=0;
memset(flag,0,sizeof(flag));
memset(used,0,sizeof(used));
memset(maxx,0,sizeof(maxx));
for(i=2;i<=n;i++){low[i]=map[1][i];mst[i]=1;}
for(i=2;i<=n;i++)
{
pos=1;
minn=maxn;
for(j=2;j<=n;j++)
if(!flag[j]&&low[j]<minn){minn=low[j];pos=j;}
used[mst[pos]][pos]=used[pos][mst[pos]]=1;
sum+=minn;
flag[pos]=1;
for(j=2;j<=n;j++)
if(flag[j])maxx[j][pos]=maxx[pos][j]=max(maxx[j][mst[pos]],low[pos]);
else if(!flag[j]&&map[pos][j]<low[j]){low[j]=map[pos][j];mst[j]=pos;}
}
if(mm(sum))return -1;
return sum;
}
int main(){
ios::sync_with_stdio(false);
int i,j,x,y,z,t,ss;
cin>>t;
while(t--){
cin>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
map[i][j]=maxn;
}
for(i=1;i<=m;i++)
{
cin>>x>>y>>z;
map[x][y]=map[y][x]=z;
}
ss=prim();
if(ss!=-1)cout<<ss<<endl;
else cout<<"Not Unique!"<<endl;
}
return 0;
}