次小生成树算法(未完成)

  次小生成树是指在一个树中除最小生成树外第二小的生成树,因此它是在最小生成树算法上衍生的。首先在求出最小生成树后,假如我们要加上一条树外的边,这样就会形成一个闭环,然后将这个闭环的最大

的边删除,那么剩下的依然是一个树,如果这个树<=最小生成树,那么它就是次小生成树。

  如果我们要加边的话,加的肯定是树外的边,这个用一个标记数组就行,然后我们还要找闭环的最大边值,

1。secondprim算法

 

2.Second_Kruskal算法

  1 struct node
  2 {
  3     //x,y表示边的左右端点,value表示边的值
  4     int x,y,value;
  5     //flag标记边是否在树上
  6     bool flag;
  7 }no[205];
  8 //n表示点数,m表示边数
  9 int n,m;
 10 //fa表示树上的顶点
 11 int fa[105];
 12 //ve用于与第i个点有连接的点
 13 vector<int> ve[105];
 14 //maxn存放两点之间的最大值
 15 int maxn[105][105];
 16 //初始化
 17 void init()
 18 {
 19     //开始时与自己相连的只有自己,同时顶点也是自己
 20     for(int i=0;i<=n;i++)
 21     {
 22         ve[i].clear();
 23         ve[i].push_back(i);
 24         fa[i]=i;
 25     }
 26 }
 27 //查找顶点
 28 int find(int x)
 29 {
 30     //如果找到顶点,则返回
 31     if(fa[x]==x)
 32     {
 33         return x;
 34     }
 35     //递归查找x的上一个点的上一个点,同时压缩路径
 36     return fa[x]=find(fa[x]);
 37 }
 38 //排序,按边的值从小到大
 39 bool cmp(node a,node b)
 40 {
 41     return a.value<b.value;
 42 }
 43 //最小生成树Kruskal算法
 44 int kruskal()
 45 {
 46     //对边进行排序
 47     sort(no+1,no+m+1,cmp);
 48     //初始化数据
 49     init();
 50     //ans表示最小生成树的权值和,cnt表示已经连接的边数
 51     int ans=0,cnt=0;
 52     //遍历所有边
 53     for(int i=1;i<=m;i++)
 54     {
 55         //如果连接了n-1个边,则表示已经连接所有的点了
 56         if(cnt==n-1)
 57         {
 58             break;
 59         }
 60         //记录当前边的两边端点的顶点
 61         int fx=find(no[i].x),fy=find(no[i].y);
 62         //如果他们不相等则进行操作
 63         if(fx!=fy)
 64         {
 65             //将fx的顶点变成fy,相当于把fx这个树的顶点挂在fy这个树顶的下面
 66             fa[fx]=fy;
 67             //生成树的边数加1
 68             cnt++;
 69             //加上这个边的权值
 70             ans+=no[i].value;
 71             //标记这个边
 72             no[i].flag=true;
 73             //对fx,fy则两颗树的所有点遍历
 74             for(int j=0;j<ve[fx].size();j++)
 75             {
 76                 for(int k=0;k<ve[fy].size();k++)
 77                 {
 78                     //将这两可树的所有点之间的最大值都变成现在变的值
 79                     //由于对no进行过排序,因此此时no[i].value的值是这个树上的最大值
 80                     maxn[ve[fx][j]][ve[fy][k]]=maxn[ve[fy][k]][ve[fx][j]]=no[i].value;
 81                 }
 82             }
 83             //对fx的树遍历,将fx树上的点都连在fy树上
 84             for(int j=0;j<ve[fx].size();j++)
 85             {
 86                 ve[fy].push_back(ve[fx][j]);
 87             }
 88         }
 89     }
 90     //如果连了n-1条边则表示有最小生成树
 91     if(cnt==n-1)
 92     {
 93         return ans;
 94     }
 95     else
 96     {
 97         return -1;
 98     }
 99 }
100 //次小生成树,mst表示最小生成树的权值和
101 int second_kruskal(int mst)
102 {
103     int ans=INF;
104     //遍历所有边
105     for(int i=1;i<=m;i++)
106     {
107         //如果这个边不在最小生成树上
108         if(!no[i].flag)
109         {
110             //计算最小生成树加外边在减内边否的最小值
111             ans=min(ans,mst+no[i].value-maxn[no[i].x][no[i].y]);
112         }
113     }
114     return ans;
115 }

 

posted @ 2019-11-09 21:43  木子川  阅读(162)  评论(0编辑  收藏  举报