破圈法求解最小生成树c语言实现(已验证)

下面是算法伪代码,每一个算法都取一个图作为输入,并返回一个边集T。

对该算法,证明T是一棵最小生成树,或者证明T不是一棵最小生成树。此外,对于每个算法,无论它是否能计算出一棵最小生成树,都要给出其最有效的实现。

MAYBE-MST-A(G,w)

Sort the edges into nonincreasing order of edge weights w

T<-E

For each edge e, taken in nonincreasing order by weight

Do if T-{e} is a connected graph

    Then T<-T-e

Return T

算法基本思想:

先将图G的边按照权的递减顺序排列后,依次检验每条边,在保持连通的情况下,每次删除最大权边,直到所有边都被遍历到无法删除任何一边(或余下n-1条边为止)。

证明:

生成树证明:

1、     如果给定连通图G没有回路,那么G本身就是一棵生成树

2、     如果G中只有一个回路,则删去G的回路上的一条边(不删除节点),则产生的图仍是连通的且没有回路,则得到的子图就是G的一棵生成树;

3、     如果G的回路不止一个,只要删去每一个回路上的一条边,知道G的子图是连通且没有回路且与图G有一样的结点集,那么这个子图就是一棵生成树。

4、     重复步骤3,则直到所有边都不能删除,由于删除判断条件,得到的子图就是一棵生成树。

MST证明:

若在某个回路C中有一条唯一的最长边,则T­­­*中一定不含这条边,因为优先删除回路中最长的边。

若在某个边e的割集中有一条唯一一条最短边,则T*中一定含有这条边(The Cut Property:考虑图G中的一条边e。如果存在一个cut(A,B),使得e是所有跨越该割的所有边中权重最小者,则e一定在G的MST中。

),且不含有其他边,因为一旦含有其他边就构成了回路(Lonely-Cut Corollary如果边e是跨越了cut(A, B)的唯一一条边,则e不可能在任一圈中。)。

反向证明:假设T*中跨越cut(A,B)的边不只一条,则在算法结束之前一定会遍历到其中的成圈的边(Double-Crossing),根据权值选取方法和删除圈的一边仍为连通图的条件,一定会将权值较大的边删除,直到无环且剩下的唯一一条边是最短边。

算法变量:

a[n][n]:带权图的邻接矩阵,a[i][j]=w或a[i][j]=0;

max:标记当前找到的准备删去的边的权值;

p:标记找到的要删去的权值所在的行号;

q:标记找到的要删去的权值所在的列好;

am:标记找到的最大元素(am是为了保护权值大但不能删的边),如果a[i][j]不能删除,则可以让a[p][q]=am,a[q][p]=am来还原刚才删去的边;

I,j:二维数组的行号和列号

sm:图的边数,每删除一个边,sm就减1,当sm=n-1时,结束

wt:最小生成树的权值和

算法实现(c语言)

 #include<stdio.h>
BY Yuanshuai Zheng,UESTC
#define n 5
int a[n][n];
int flag,am,p,q;
INPUT()
{
int i,j;
printf("输入图的带权邻接矩阵:\n");
for(i = ;i<n;i++)
{
for(j=;j<n;j++)
scanf("%d",&a[i][j]);
}
}
OUTPUT(int a[n][n])
{
int i,j;
for(i=;i<n;i++)
{
for(j=;j<n;j++)
printf("%5d",a[i][j]);
printf("\n");
}
}
MAX(int a1[n][n],int am1,int p1,int q1)
{
int i,j,ptm,qtm;
int max;
max = ;
for(i=;i<n;i++)
{
for(j=i;j<n;j++)
if((a1[i][j]>max)&&(a1[i][j]<=am1)&&((i!=p1)||(j!=q1)))
{
max = a1[i][j];
ptm = i;
qtm = j; }
}
am = max;
printf("max=%5d\t",am);
p = ptm;
q = qtm;
a[p][q]=;
a[q][p]=;
}
WSHALL(int array[n][n])
{
int i,j,k,m=;
int r[n][n],B[n][n];
for(i=;i<n;i++)
{
for(j=;j<n;j++)
{
r[i][j]=;
B[i][j]=array[i][j];
//分界线
if(array[i][j]>=)
B[i][j]=;
else
B[i][j]=;
//分界线
}
}
for(j=;j<n;j++)
{
for(i=;i<n;i++)
if(B[i][j]>=)
{
for(k=;k<n;k++)
{
if(B[k][i]>=)
{
B[k][j]=B[j][k]=;
}
}
}
}
for(i=;i<n;i++)
{
for(j=;j<n;j++)
if(!B[i][j])
{
return ;
}
}
return ;
} //方法1
// for(k=0;k<n;k++)
// B[i][j]=B[i][k]+B[j][k];
// }
// }
// for(i=0;i<n;i++)
// {
// for(j=0;j<n;j++)
// {
// r[i][j]=B[i][j];
// {
// if((r[i][j]>=1)||(i==j))
// m=m+1;
// }
// }
// }
// printf("m=%d\t",m);
// if(m==n*n)
// flag = 1;
// else
// flag=0;
// return(flag); int main()
{
int i,j,sm,wt=;
am = ,p=-,q=-,sm=;
INPUT();
for(i=;i<n;i++)
{
for(j=i;j<n;j++)
{
if(a[i][j]>)
sm = sm+;
}
}
printf("\nsm=%d\n",sm);
printf("输出图的带权邻接矩阵:\n");
OUTPUT(a);
printf("\n");
while(sm>n-)
{
MAX(a,am,p,q);
flag=WSHALL(a);//华沙尔算法判断是否连通
//printf("flag= %d",flag);
{
if(flag==)
{
sm=sm-;
//printf("flag= %d",flag);
}
else
{
a[p][q]=am;
a[q][p]=am;
}
}
}
for(i=;i<n;i++)
for(j=i;j<n;j++)
{
wt=wt+a[i][j];
}
printf("\n\n输出最小生成树的带权邻接矩阵:\n");
OUTPUT(a);
printf("最小生成树的树权是: %d\n",wt);
}

代码验证:

例子:

0

6

10

0

0

6

0

3

8

5

10

3

0

6

7

0

8

6

0

0

0

5

7

0

0

破圈法求解最小生成树c语言实现(已验证)的更多相关文章

  1. CF F. MST Unification (最小生成树避圈法)

    题意 给一个无向加权联通图,没有重边和环.在这个图中可能存在多个最小生成树(MST),你可以进行以下操作:选择某条边使其权值加一,使得MST权值不变且唯一.求最少的操作次数. 分系:首先我们先要知道为 ...

  2. Eratosthenes筛选法求解质数

    问题说明: 除了自身之外,无法被其它整数整除的数称之为质数,要求质数很简单,但如何快速的求出质数则一直是程式设计人员与数学家努力的课题, 在这边介绍一个着名的 Eratosthenes求质数方法. 解 ...

  3. uva11549 Floyd判圈法

    题意: 给两个数n, k,每次将k平方取k的前n位,问所有出现过的数的最大值 原来这就是floyd判圈法.. #include<cstdio> #include<cstdlib> ...

  4. POJ 2135.Farm Tour 消负圈法最小费用最大流

    Evacuation Plan Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4914   Accepted: 1284   ...

  5. UOJ 117 欧拉回路(套圈法+欧拉回路路径输出+骚操作)

    题目链接:http://uoj.ac/problem/117 题目大意: 解题思路:先判断度数: 若G为有向图,欧拉回路的点的出度等于入度. 若G为无向图,欧拉回路的点的度数位偶数. 然后判断连通性, ...

  6. POJ 1061 青蛙的约会(拓展欧几里得算法求解模线性方程组详解)

    题目链接: BZOJ: https://www.lydsy.com/JudgeOnline/problem.php?id=1477 POJ: https://cn.vjudge.net/problem ...

  7. Coursera在线学习---第一节.梯度下降法与正规方程法求解模型参数比较

    一.梯度下降法 优点:即使特征变量的维度n很大,该方法依然很有效 缺点:1)需要选择学习速率α 2)需要多次迭代 二.正规方程法(Normal Equation) 该方法可以一次性求解参数Θ 优点:1 ...

  8. 基本算法思想之递推算法思想(C++语言描述)

    递推算法是非常常用的算法思想,在数学计算等场合有着广泛的应用.递推算法适合有明显公式规律的场合. 递推算法基本思想 递推算法是一种理性思维莫斯的代表,根据已有的数据和关系,逐步推到而得到结果.递推算法 ...

  9. 逆波兰法求解数学表达示(C++)

    主要是栈的应用,里面有两个函数deleteSpace(),stringToDouble()在我还有一篇博客其中:对string的一些扩展函数. 本程序仅仅是主要的功能实现,没有差错控制. #inclu ...

随机推荐

  1. div+css显示两行或三行文字,超出用...表示

    <style> .comment_inner{ width: 200px; word-break: break-all; text-overflow: ellipsis; display: ...

  2. mysql 查询 练习题及答案

    CREATE DATABASE school;USE school;/*1.创建student表格*//*id为主键 非空 唯一 */CREATE TABLE student (id INT(10) ...

  3. 小甲鱼零基础python课后题 P22 021函数:lambda表达式

    0.请使用lambda表达式将下边函数转变为匿名函数 def fun_A(x,y=3): return x*y 答: lambda x,y=3:x*y 1.请将下边的匿名函数转变为普通的屌丝函数 la ...

  4. LeetCode 50 - Pow(x, n) - [快速幂]

    实现 pow(x, n) ,即计算 x 的 n 次幂函数. 示例 1: 输入: 2.00000, 10输出: 1024.00000 示例 2: 输入: 2.10000, 3输出: 9.26100 示例 ...

  5. Gym 101606B - Breaking Biscuits - [凸包+旋转卡壳][凸包的宽度]

    题目链接:https://codeforces.com/gym/101606/problem/B 题解: 对于给出的 $n$ 个点,先求这些点的凸包,然后用旋转卡壳求出凸包的宽度(Width (min ...

  6. vue中路由懒加载实现amd加载文件

    一般我们配置路由的时候是import引入: import log from '@/components/login': { path: '/login', component: log , hidde ...

  7. Pycharm 自定义文件模板

    Pycharm 自定义文件模板 每次新建文件都有相同的代码框架,每次重复敲浪费了程序员的寿命啊 按照下面方式自定义自己的模板:

  8. hisi35xx串口驱动的完善

    鉴于hisi的uart3还没有打通,ls /dev/ | grep ttyA* ,看到的只有ttyAMA0 和ttyAMA1,且使用应用程序打开ttyAMA1设备后,使用write函数,发送,示波器观 ...

  9. 【JVM】-NO.113.JVM.1 -【JDK11 HashMap详解-4-resize()】

    Style:Mac Series:Java Since:2018-09-10 End:2018-09-10 Total Hours:1 Degree Of Diffculty:5 Degree Of ...

  10. Django 分组 聚合

    base_sql = Order.objects.filter(is_paid=True, merchant=merchant_id) # 如果aggregate前没有values,得到的结果是一个字 ...