通信网络设计问题(kruskal求最短路)

title: 通信网络设计问题(kruskal求最短路)
date: 2019-08-24 23:34:43
tags: 数学建模

某通信公司拟建一个具有80个结点的通信网络,需要在这些结点之间铺设线路,进行数据传输。结点之间的距离和铺设线路的单位费用见附件1,请对以下问题进行研究:

问题1.要使得通信网络的总铺设费用最省,请建立问题的数学模型,设计求解算法,给出铺设方案,并讨论方案的可靠性;

解决:我们采用kruskal算法找出最短路,再依次断开每个点,计算最大连通分支里的节点数,从而计算出可靠性,再进行分析

注意:graphconncomp命令的使用,它可以用来求连通分支,功能有点像并查集啥的,但是更方便…对于矩阵存储也更合适,再用C++敲我就是猪…

%  kruskal算法
function [result]=kruskal(a)
% 输入:a—邻接矩阵,a(i,j)是指i到j之间的权值
% 输出:result—第一、二、三行分别代表最小生成树边的起点、终点、权集合
[i,j,b]=find(a);
data=[i';j';b'];index=data(1:2,:);
loop=length(a)-1;
result=[];
while length(result)<loop
   temp=min(data(3,:));
   flag=find(data(3,:)==temp);
   flag=flag(1);
   v1=index(1,flag);v2=index(2,flag);
   if v1~=v2
      result=[result,data(:,flag)];
   end
   index(find(index==v2))=v1;
   data(:,flag)=[];
   index(:,flag)=[];
end
end
%以下部分在命令窗口中输入,以绘制生成的最短路图
%kruskal(a)  %a中导入边权
%A=ans(1,:);
%B=ans(2,:);
%C=ans(3,:);
%SS=sparse(A,B,C,80,80);
%view(biograph(ST,[],'ShowArrows','off','ShowWeights','on'))
#include <iostream>
#include <map>
#include <algorithm>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <stdlib.h>
#define ll long long
const int maxn=105;
const int inf=0x3f3f3f3f;
const double eps=1e-6;
using namespace std;
int nodenum[maxn];
int parent[maxn];
int find_root(int x)
{
	if(x!=parent[x])
	parent[x]=find_root(parent[x]);
	return parent[x];
}
void Union(int x,int y)
{
	int rx=find_root(x);
	int ry=find_root(y);
	if(rx==ry)
	return;
	else
	{
		parent[ry]=rx;
		nodenum[rx]+=nodenum[ry];
	}
}
int main()
{
   freopen("in1.txt","r",stdin);
   //freopen("out.txt","w",stdout);
   int t=80;
   for(int k=1;k<=80;k++)
   {
	int n=79;
	for(int i=0;i<maxn;i++)
	{
		parent[i]=i;
		nodenum[i]=1;
	}
	int maxnode=80;
	int v,w;
	//for(int i=1;i<=n;i++)
	while(scanf("%d%d",&v,&w)&&v&&w) 
	{
		Union(v,w);
	}
	int cnt=0;
	int ans[maxn];
	for(int i=0;i<maxn;i++)
	ans[i]=0;
	int f[maxn]; 
	int maxi=-1;
	for(int i=1;i<=maxnode;i++)
	{
		if(parent[i]==i)
		{
			ans[cnt]=nodenum[i];
			if(nodenum[i]>maxi)
			maxi=nodenum[i];
			//f[cnt]=i;
			cnt++;
		}
	}
	//for(int i=0;i<cnt;i++)
	//cout<<f[i]<<endl;
	//cout<<"去掉第"<<k<<"个结点:\t"<<
	cout<<"块数:"<<cnt<<"   \t每个块节点个数:";
	for(int i=0;i<cnt;i++)
	cout<<ans[i]<<"  ";
	cout<<endl;
	
	double t=maxi/80.0;
	cout<<"可靠性:"<<t<<endl;
   }
	return 0;
}

问题2.考虑到通信网络结点的可靠性,若要求任意一个结点出现故障时,其它结点间仍然能够保持通信畅通的可能性都达到90%,请建立问题的数学模型,设计求解算法,并给出使总铺设费用最少的铺设方案;

解决:相当于从第一问取出可靠性最低的点,然后找出避开这个点,再把几个块连接起来,使其达到90%可靠性要求,再次遍历80个点,找不满足可靠性要求的点,再给他们加边

注意:其实没有办法找到最优解,只能无限接近它,设定为全部结点到达90%可靠性退出循环时,产生了死循环,所以我们设定允许2~3个结点可以不达到90%时,可以得到较优的结果

function main()
A=[];
B=[];
%A,B构成系数矩阵
D=[];%放边权的邻接矩阵
global G;
G=sparse(A,B,true,80,80);% 构造稀疏矩阵
global t;
global num;
global temp;
global S;
%k=3;
sum=0;
func3();
while(1)
        minx=1;
        cn=0;
        for i=1:80
        if(t(i)<minx)
            minx=t(i);
            mint=i;%记录了当前最小的那个结点
        end
        if(t(i)<0.9)
            cn=cn+1;
        end
        end
        %mint
        
        if(cn<3)%都大于90%了
            break;
        end
        %找到最小结点mint了,要求出连接的两块的最短路minl 
        func1(mint);
        m=0;
        n=0;
        mi=0;
        %num
        for i=1:S
            if(num(i)>mi)
                mi=num(i);
                m=i;
            end
        end
        mii=0;
        for i=1:S
            if(num(i)~=mi&&num(i)>mii)
                    mii=num(i);
                    n=i;
            end
        end
        %temp
         % m
         % n
        a=temp{m};
        b=temp{n};
        
        c=D(a,b);
        mind=min(min(c));
        sum=sum+mind;
        mind
        [x,y]=find(D==mind);
       %连接起来,再次计算每个点的可靠性
       x1=x(1);
       y1=y(1);
        G(x1,y1)=1;
        G(y1,x1)=1;
        func3();
        %t
        x1
        y1
       % k=k-1;
        
end
sum
%可求出1~80号结点的可靠性
function p=func3()
global t;
for i=1:80
    t(i)=func1(i);
end


%求出每一组的可靠性
function ans=func1(k)
global G;
g=G;
g(k,:)=0;
g(:,k)=0;
global S;
[S,C] = graphconncomp(g);
global temp;
global num;
temp=cell(S,1);
for i=1:S
    z=find(C==i);
    temp{i}=z;
    num(i)=length(z);
end
temp;

%求可靠性
maxn=0;
for i=1:S
    if(num(i)>maxn)
        maxn=num(i);
    end
end
ans=maxn/80;

问题3:考虑到通信网络链路的可靠性,若要求任意一条链路被破坏时,能够保持通信畅通的结点都能够达到90%,请建立问题的数学模型,设计求解算法,并给出使总铺设费用最少的铺设方案。

解决:第三问和第二问差不多求解,甚至更为简单,因为每次断开一条边,只会把所有的点分成两个部分

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kruskal算法是一种用来解最小生成树的贪心算法。它的基本思想是,按照边的权值从小到大的顺序选择边,并且保证所选的边不会形成环,直到选取了n-1条边为止。另外,Kruskal算法还需要使用并查集来判断两个节点是否属于同一个连通分量。 在具体的实现过程中,可以按照以下步骤进行: 1. 将图中的所有边按照权值从小到大排序。 2. 创建一个并查集,并初始化每个节点为一个独立的集合。 3. 遍历排序后的边列表,对于每一条边(u, v),判断u和v是否属于同一个连通分量。如果不属于,则将这条边加入最小生成树中,并将u和v合并到同一个连通分量中。 4. 重复步骤3,直到最小生成树中的边数达到n-1。 通过以上步骤,就可以使用Kruskal算法解出给定图的最小生成树。 参考资料: 引用:(1)度限制最小生成树和第K最短路. (poj1639) (2)最短路,最小生成树,二分图,最大流问题的相关理论(主要是模型建立和解) (poj3155, poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446 (3)最优比率生成树. (poj2728) (4)最小树形图(poj3164) (5)次小生成树. (6)无向图、有向图的最小环 。 引用:http://home.ustc.edu.cn/~zhuhcheng/ACM/segment_tree.pdf 。 引用:练习复杂一点,但也较常用的算法。 二分图匹配(匈牙利),最小路径覆盖 网络流,最小费用流。 线段树. 并查集。 熟悉动态规划的各个典型:LCS、最长递增子串、三角剖分、记忆化dp 6.博弈类算法。博弈树,二进制法等。 7.最大团,最大独立集。 8.判断点在多边形内。 差分约束系统. 双向广度搜索、A*算法,最小耗散优先. 第三阶段: 。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值