次小生成树

所谓次小生成树,顾名思义就是从生成树中取出的第二小的生成树。

我们在前面已经说过最小生成树的概念及代码实现了,所以接下来要说的次小生成树应该比较简单理解了。

求次小生成树的两种方法

1:首先求出最小生成树T,然后枚举最小生成树上的边,计算除了枚举的当前最小
生成树的边以外的所有边形成的最小生成树Ti,然后求最小的Ti就是次小生成树。
2:首先计算出最小生成树T,然后对最小生成树上任意不相邻的两个点 (i,j)
添加最小生成树以外的存在的边形成环,然后寻找i与j之间最小生成树上最长的边删去,
计算map[i][j](最小生成树以外存在的边) 与 maxd[i][j](最小生成树上最长的边)
差值,求出最小的来,w(T)再加上最小的差值就是次小生成树了。

 

给定一个图,询问该图的最小生成树与次小生成树是否一致。

 Kruscal实现版:

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct nond{
    int x,y,z;
}edge[101*101];
int T,N,M,x,y,z,fa[1000],num,ans[1000];
int tot,bns,k,answer=9999999;
int cmp(nond aa,nond bb){
    return aa.z<bb.z;
}
int find(int x){
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
int main(){
    cin>>T;
    while(T--){
        cin>>N>>M;
        tot=0;bns=0;
        answer=9999999;
        memset(fa,0,sizeof(fa));
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=M;i++){
            cin>>x>>y>>z;
            edge[i].x=x;
            edge[i].y=y;
            edge[i].z=z;
        }
        sort(edge+1,edge+1+M,cmp);
        for(int i=1;i<=N;i++)    fa[i]=i;
        for(int i=1;i<=M;i++){
            int dx=find(edge[i].x),dy=find(edge[i].y);
            if(dx!=dy){
                fa[dx]=dy;
                tot++;
                ans[tot]=i;
                bns+=edge[i].z;
            }
            if(tot==N-1)    break;
        }
        for(int i=1;i<=tot;i++){
            k=0;num=0;
            for(int j=1;j<=N;j++)    fa[j]=j;
            sort(edge+1,edge+1+M,cmp);
            for(int j=1;j<=M;j++){
                if(j==ans[i])    continue;
                int dx=find(edge[j].x),dy=find(edge[j].y);
                if(dx!=dy){
                    fa[dx]=dy;
                    num++;
                    k+=edge[j].z;
                }
                if(num==N-1)    break;
            }
            if(num==N-1) answer=min(k,answer);
        }
        if(answer==bns)    cout<<"Not Unique!"<<endl;
        else    cout<<bns<<endl;
    }
} 

 

prim实现版

代码;

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int inf = 0x7fffffff;
const int size = 501;

int firstpath[size][size];
int secondpath[size][size];
int pre[size];
int d[size];
int tree[size];
int t=0;
bool flag[size];
int V,E;

int qmax(int x,int y)
{
   if(x>y)return x;
   else return y;
}

void prime(int u)
{
   int i,j;
   for(i=1;i<=V;++i)
    {
      flag[i]=false;
      d[i]=inf;
    }
   for(i=1;i<=V;++i)
    for(j=i;j<=V;++j)
     secondpath[i][j]=secondpath[j][i]=-1;
   t=0;
   tree[t++]=u;
   flag[u]=true;

   for(i=1;i<V;++i)
    {
       int min=inf;
       int k;
       for(j=1;j<=V;++j)
        {
           if(d[j]>firstpath[u][j])
            {
              d[j]=firstpath[u][j];
              pre[j]=u;
            }
           if(!flag[j] && d[j]<min)
            {
               min=d[j];
               k=j;
            }
        }

        for(j=0,u=k;j<t;++j)
         {
           secondpath[tree[j]][u]=qmax(secondpath[tree[j]][pre[u]],d[u]);
           secondpath[u][tree[j]]=secondpath[tree[j]][u];
         }
       firstpath[pre[u]][u]=firstpath[u][pre[u]]=inf;
       flag[u]=true;
       tree[t++]=u;
    }

   for(i=1;i<=V;++i)
    for(j=i+1;j<=V;++j)
     if(firstpath[i][j]!=inf && firstpath[i][j]==secondpath[j][i])
      {
        printf("Yes\n");
        return ;
      }
   printf("No\n");
}

int main()
{
   int i,T,j,x,y,z;
   scanf("%d",&T);
   while(T--)
    {
      scanf("%d%d",&V,&E);
      for(i=1;i<=V;++i)
       for(j=i;j<=V;++j)
        firstpath[i][j]=firstpath[j][i]=inf;
      for(i=0;i<E;++i)
       {
          scanf("%d%d%d",&x,&y,&z);
          firstpath[x][y]=firstpath[y][x]=z;
       }
      prime(1);
    }
   return 0;
}

转载于:https://www.cnblogs.com/z360/p/6875488.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值