两点间多条最短路径

最短路径的求法可能都知道,弗洛伊德和迪克斯特拉。这两种方法都是求一条最短路径,如果你想求多条最短路径那就只能选择其他方法了。

网上已经有几种算法可以求多条最短路径,最常见的就是删边法+迪克斯特拉。就是用狄克斯特拉求出一条最短路径然后把最短路径上的边一条一条的删除然后再求最短路径。

这个方法比较容易想但是删边的时候比较麻烦。

那么我们可不可以在floyd的方法上改进呢,我们想一想floyd的判断方法是什么if(A[i][j] > A[i][k]+A[k][j]) 我们就更换A[I][j],并且记录路径;

细心的人可能会发现我们既然可以用 > 筛选一条最短路径那么我们改变判断条件 让A[i][j] == A[i][k]+A[k][j]时我们保存他们的路径。当然这是可以的,但是现有的二维储存路径已经满足不了了,必须改用三维我选用的是二维的vector(vector<int> path[][]).当大于时我们清除path当等于时我们增加path。代码实现如下。

for (k =0 ; k< n; k++)
	{
		for (i = 0; i< n; i++)
			for (j = 0; j< n; j++)
				if (a[i][j] > a[i][k] + a[k][j])
				{
					a[i][j] = a[i][k]+a[k][j];
					path[i][j].clear();
					path[i][j].push_back(k);
					f[i][j] = f[i][k]*f[k][j];
				}
				else if (a[i][j] == a[i][k] + a[k][j] && k!= i &&k !=j)
				{
					path[i][j].push_back(k);
					f[i][j]+= f[i][k]*f[k][j];
				}
	}

假如我们想知道有多少条最短路径,我们先思考这个问题,高中时我们学过排列组合有三个地点 A B C, A到B有3条路径, B到C有2条路径。那么A到C就有6条路径,这个是简单的排列组合问题。我们回到刚才的话题,I到J的路径多少也等于i到k的路径乘上k到J的路径,如上面的f数组。

当你想知道路过什么点时你可以用书上的递归式来获得当然你需要一点小的变动,如下

	k = path[i][j].size();
	if (k == 0)
	{
		b[j]++;
		return;
	}
	for (m = 0;m < path[i][j].size(); m++)
	{
		Ppath(i, path[i][j][m]);
		Ppath(path[i][j][m], j);
	}


到此分析结束,你再也不用为多条最短路径烦恼了


#pragma once
#include <iostream>
#include <vector>
using namespace std;

// floyd

class floyd : public CWnd
{
	DECLARE_DYNAMIC(floyd)

public:
	floyd();
	virtual ~floyd();

protected:
	DECLARE_MESSAGE_MAP()
public:
	int n;
	double c[100];
	int b[100];
	int f[100][100];
	int a[100][100];
	vector<int>path[100][100];
	string name[100];
	void Ppath(int i, int j);
	void Dispath();
	void Floyd();
};



 
#include "stdafx.h"
#include "Knowledge_Graph.h"
#include "floyd.h"
#include <iostream>
#include <fstream>
using namespace std;
 
// floyd
 
IMPLEMENT_DYNAMIC(floyd, CWnd)
 
floyd::floyd()
{
    memset(b, 0, sizeof(b));
    memset(c, 0, sizeof(c));
    int i, j;
    for (i = 0; i<100; i++)
    {
        for (j = 0; j< 100; j++)
        {
            a[i][j] = 0;
            f[i][j] = 0;
        }
    }
}
 
floyd::~floyd()
{
}
 
 
BEGIN_MESSAGE_MAP(floyd, CWnd)
END_MESSAGE_MAP()
 
 
 
// floyd 消息处理程序
 
 
 
void floyd::Ppath(int i, int j)
{
    int k, m;
    k = path[i][j].size();
    if (k == 0)
    {
        b[j]++;
        return;
    }
    for (m = 0;m < path[i][j].size(); m++)
    {
        Ppath(i, path[i][j][m]);
        Ppath(path[i][j][m], j);
    }
}
 
void floyd::Floyd()
{
    ofstream ofs("hebo_jiejinzhongxindu.txt",ios::out);
    ofstream ofs1("hebo_dushuzhongxindu.txt",ios::out);
    int i, j, k;
    int dis[100]={0};
    for (i = 0; i<n; i++)
    {
        k = 0;
        for (j = 0; j<n;j++)
        {
            if (a[i][j] == 1)
            {
                k++;
            }
        }
        ofs1<<name[i]<<"    ";
        ofs1<<k<<endl;
    }
    for (k =0 ; k< n; k++)
    {
        for (i = 0; i< n; i++)
            for (j = 0; j< n; j++)
                if (a[i][j] > a[i][k] + a[k][j])
                {
                    a[i][j] = a[i][k]+a[k][j];
                    path[i][j].clear();
                    path[i][j].push_back(k);
                    f[i][j] = f[i][k]*f[k][j];
                }
                else if (a[i][j] == a[i][k] + a[k][j] && k!= i &&k !=j)
                {
                    path[i][j].push_back(k);
                    f[i][j]+= f[i][k]*f[k][j];
                }
    }
    for (i = 0; i<n; i++)
    {
        for (j = 0; j<n; j++)
        {
            dis[i]+=a[i][j];
        }
        ofs<<name[i]<<" ";
        ofs <<dis[i]<<endl;
    }
    Dispath();
}
void floyd::Dispath()
{
    ofstream ofs("hebo_zhongjianzhongxinxing.txt",ios::out);
    int i, k, j;
    for (i = 0; i< n; i++)
        for (j = 0; j< n; j++)
        {
            if (a[i][j] != 1000)
            {
                Ppath(i, j);
                for (k = 0; k<n; k++)
                {
                    if (k!= i && k!=j && f[i][j]>0)
                    {
                        c[k]=c[k]+b[k]*1.0/f[i][j];
                    }
                }
                memset(b, 0, sizeof(b));
            }
        }
        for (i = 0; i < n; i++)
        {
            ofs<<name[i]<<" ";
            ofs <<c[i]<<endl;
        }   
}


工作后时间太忙了,只是利用博客查看资料,也没关注过自己的博客,看到这么多朋友有需求,就贴出全部代码吧,应该编译不过,但是你们应该可以看懂啦。汲取了那么多前辈的知识,也要学着付出啦


评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值