最小生成树拓展

对于一个连通图,输出最多能删除多少条边,使这个图仍连通。

Input:  N M //N—顶点数,M—边数

          v1 v2

          …… //M 行

Output:  删除的边个数及各边

这是几天前老师给我们讲了最小生成树后出的一道题,留给大家思考并求解。)

  解题思路:连通图是个不带权的无向图,而有向图是强连通图(若非老师提醒,大家都迷糊了)。其中删除的边数很容易求出,不需要后面的M行边的输入,直接就可以求出是M-(N-1),要使这个图仍连通所需要的最少的边是顶点数减1,即最小生成树。关键就是怎样求这些要删除的边,我知道还是要用到最小生成树的算法,老师的一句话提醒了我们,可以把这个图的每条边权值都赋为1,然后再用普里姆(Prim)算法建立最小生成树。我就顺着这个思路开始敲代码,我把最小生成树中的边赋值为2,与可删除的边区分开来。当然开始把每两个顶点之间的距离初始化为最大值。最后输出距离为1的边就是要删除的边。可是还是有问题,我这个答案只是其中一个解,由于图中各边的权值相同,删除的边就不一定了,因为最小生成树并不唯一。(不过我还会寻找更好的解决方法。)

代码如下:

ExpandedBlockStart.gif View Code
 1  #include < iostream >
 2  using   namespace  std;
 3  #define  Max 100
 4  int  map[Max][Max],n,m;
 5  struct {
 6       int  adjvex;
 7       int  lowcost;
 8  }closedge[Max];
 9  void  prim( int  k) // 普里姆算法
10  {
11       int  i,j;
12       for (j = 1 ;j <= n;j ++ )
13           if (j != k){ closedge[j].adjvex = k; closedge[j].lowcost = map[k][j]; }
14      closedge[k].lowcost = 0 ;
15       for (i = 1 ;i < n;i ++ )
16      {
17           int  min = Max;
18           for (j = 1 ;j <= n;j ++ )
19              if (closedge[j].lowcost != 0 && min > closedge[j].lowcost)
20             {
21                 min = closedge[j].lowcost;
22                 k = j;
23             }
24          map[closedge[k].adjvex][k] = map[k][closedge[k].adjvex] = 2 ; // 把最小生成树中的边赋值为2
25          cout << closedge[k].adjvex << " " << k << endl;
26          closedge[k].lowcost = 0 ;
27           for (j = 1 ;j <= n;j ++ )
28              if (map[k][j] < closedge[j].lowcost)
29             {
30                 closedge[j].adjvex = k;
31                 closedge[j].lowcost = map[k][j];
32             }
33      }
34  }
35  int  main()
36  {
37      int  i,j,a,b;
38     cin >> n >> m;
39      for (i = 1 ;i <= n;i ++ ) // 初始化
40     {
41        closedge[i].lowcost = Max;
42         for (j = 1 ;j <= n;j ++ )
43            map[i][j] = Max;
44     }
45      for (i = 0 ;i < m;i ++ )
46     {
47         cin >> a >> b;
48         map[a][b] = map[b][a] = 1 ;
49     }
50     prim( 1 );
51     cout << " 最多删除的边的个数为: " << m - (n - 1 ) << endl;
52     cout << " 删除的边为: " << endl;
53      for (i = 1 ;i <= n;i ++ )
54          for (j = 1 ;j < i;j ++ )
55              if (map[i][j] == 1 ) cout << j << " " << i << endl;
56       return   0 ;
57  }

 

转载于:https://www.cnblogs.com/yueshuqiao/archive/2011/08/26/2155120.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值