poj 1679

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}


猜你喜欢

转载自blog.csdn.net/Masqueradey/article/details/52648212