分支限界法单源点最短路径问题(转)

单源点最短路径问题

贪心法,分支限界法

是一个顺序的贪心过程.操作基础是集合

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
#define    MAXN 100
#define INF 0x3f3f3f3f

int a[MAXN][MAXN];    //存储图
int dist[MAXN], vis[MAXN];    //dist[]点到当前点的距离, vis[]用来判断是否走过当前路径
vector<int> pre[MAXN];    //存储前驱结点
vector<int> ans; //用于存储结果路径
int n, m, s, t;    //n个结点,m条边,s是源点, t为目标点

struct NodeType {
	int vno;
	int length;
	bool operator<(const NodeType &e) const {
		return length > e.length;    //length越小越优先出队
	}
};

void Init() {
	int x, y, len;
	cout << "请依次输入结点个数、边数、源点、目标点" << endl;
	cin >> n >> m >> s >> t;
	memset(dist, INF, sizeof(dist));
	memset(a, INF, sizeof(a));
	memset(vis, 0, sizeof(vis));
	for(int i = 0; i < m; i++) {  //建图--有向图
		cin >> x >> y >> len;
		a[x][y] = len;
	}
}

void bfs() {
	NodeType e, e1;
	queue<NodeType> pqu;
	e.vno = s;
	e.length = 0;
	pqu.push(e);
	dist[s] = 0;

	while(!pqu.empty()) {
		e = pqu.front();
		pqu.pop();
		for(int j = 0; j < n; j++) {
			if(a[e.vno][j] < INF && e.length+a[e.vno][j] < dist[j] && !vis[j]) {
				//剪枝:e.vno到顶点j有边并且路径长度更短
				dist[j] = e.length + a[e.vno][j];
				pre[j].clear();
				pre[j].push_back(e.vno);
				e1.vno = j;    //建立相邻点j的结点e1
				e1.length = dist[j];
				pqu.push(e1);
			} else if(a[e.vno][j] < INF && e.length+a[e.vno][j] == dist[j] && !vis[j]) {
				pre[j].push_back(e.vno);
				e1.vno = j;    //建立相邻点j的结点e1
				e1.length = dist[j];
				pqu.push(e1);
			}
		}

	}

}

void OutPutPath(int i) {
	for(int j = 0; j < pre[i].size(); j++) {
		ans.push_back(pre[i][j]);
		if(pre[i][j] == s) {
			for(int k = ans.size()-1; k >= 0; k--) {
				cout << ans[k] <<" ";
			}
			cout <<"\n";
		}
		OutPutPath(pre[i][j]);    //往下一层
		ans.pop_back();    //删除上个元素
	}
}

void OutPut() {
	cout << "点" << s << "到"<< t << "的最短距离是" << dist[t] << endl;
	cout << "路径为:";
	OutPutPath(t);
}

int main() {
	Init();
	bfs();
	ans.push_back(t);
	OutPut();
	return 0;
}
/*
结果测试
请依次输入结点个数、边数、源点、目标点
6 8 0 5
0 2 10
0 4 30
0 5 60
2 3 50
4 3 20
4 5 60
3 5 10
1 2 4
点0到5的最短距离是60
路径为:0 5
0 4 3 5

https://my.oschina.net/u/4395907/blog/3356489

*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值