您的位置:首页 > 其它

暑假-最短路(Bellman-ford、spfa)-C - Minimum Transport Cost

2015-08-18 20:14 363 查看
题意:有n个城市,然后给你n*n的矩阵,map[i][j]代表:值为-1即表示没有从i到j的路,

否则存在i到j的路,并且路费的map[i][j]的值,然后每经过一个城市都要交税(除了起点和终点外)

n等于0时程序结束,然后给你起点和终点,输出从起点和终点的最小费用和路径。

费用=路费+税。

注意:若存在几条路径的费用一样,则要输出字典序最小的那条。

(如:从1->3的费用为3,从1->2->3的费用也是3,那么就要输出第二条路径)

思路:SPFA,Floy,Dijkstra

Floy最方便,其他两个在输出字典序最小的那条路比较麻烦。

SPFA算法:

<在输出字典序最小的路径上面卡死了,WA了8次。实在无力去找题解才发现可以用直接把2条路径放出

在判断哪个是字典序最小,T T>

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN = 105;
#define INF 0x3f3f3f3f//无穷大
int inq[MAXN], tax[MAXN], map[MAXN][MAXN];//点是否算过,税,路费
int path[MAXN][MAXN], dist[MAXN][MAXN];//保存路径,值
int n;
bool chang(int v0, int u, int v)//判断字典序是否是最小
{//从v0->...->v的路径,和v0->...->u->v的路径比较取字典序小的
	int p1[MAXN], p2[MAXN];
	//v0->...->v的路径,v0->...->u->v的路径
	int len1 = 0, len2 = 0, tmp;
	memset(p1, 0, sizeof(p1));
	memset(p2, 0, sizeof(p2));

	p1[len1] = v;//v0->...->v的路径
	tmp = path[v0][v];
	while (tmp != v0)
	{
		p1[++len1] = tmp;
		tmp = path[v0][tmp];
	}
	p1[++len1] = tmp;

	p2[len2] = v;// v0->...->u->v的路径
	tmp = u;
	while (tmp != v0)
	{
		p2[++len2] = tmp;
		tmp = path[v0][tmp];
	}
	p2[++len2] = tmp;

	while (p1[len1] == p2[len2])//从开始一一判断
	{
		len1--; len2--;
	}

	return p2[len2]<p1[len1];
}
void SPFA(int v0)//SPFA算法
{
	int i, u;
	queue<int>q;
	for (i = 1; i <= n; i++)
	{
		inq[i] = 0;
		dist[v0][i] = map[v0][i];
		path[v0][i] = v0;
	}
	dist[v0][v0] = 0;
	for (i = 1; i <= n; i++)
	{
		if (dist[v0][i] != INF)
		{
			q.push(i);
			inq[i] = 1;
		}
	}
	while (!q.empty())
	{
		u = q.front();
		q.pop();
		inq[u]--;
		for (int v = 1; v <= n; v++)
		{
			if (dist[v0][v]>(dist[v0][u] + map[u][v] + tax[u]))
			{
				dist[v0][v] = (dist[v0][u] + map[u][v] + tax[u]);
				path[v0][v] = u;
				if (!inq[v])
				{
					q.push(v);
					inq[v]++;
				}
			}
			else if (dist[v0][v] == (dist[v0][u] + map[u][v] + tax[u]))
			{
				if (chang(v0, u, v))//费用相同判断路径是否满足字典序最小
				{
					path[v0][v] = u;
				}
			}
		}
	}
}
int main()
{
	while (cin >> n)
	{
		if (!n)
		{
			break;
		}
		int  Start, End;
		for (int i = 1; i <= n; i++)//路费
		{
			for (int j = 1; j <= n; j++)
			{
				cin >> map[i][j];
				if (map[i][j] == -1)//无路
				{
					map[i][j] = INF;
				}
			}
		}
		for (int i = 1; i <= n; i++)//对应城市的税
		{
			cin >> tax[i];
		}
		for (int i = 1; i <= n; i++)//预先把所有求出来。
		{
			SPFA(i);
		}
		while (cin >> Start >> End)//开始和结束,然后按照案例输出
		{
			if (Start == -1 && End == -1)
			{
				break;
			}
			if (Start == End)
			{
				cout << "From " << Start << " to " << End << " :" << endl;
				cout << "Path: " << Start << endl;
				cout << "Total cost : " << 0 << endl << endl;
				continue;
			}
			int shorttest[MAXN], k = 0;
			cout << "From " << Start << " to " << End << " :" << endl;
			cout << "Path: ";
			shorttest[k] = End;
			while (path[Start][shorttest[k]] != Start)
			{
				k++;
				shorttest[k] = path[Start][shorttest[k - 1]];
			}
			k++;
			shorttest[k] = Start;
			for (int j = k; j > 0; j--)
			{
				cout << shorttest[j] << "-->";
			}
			cout << shorttest[0] << endl;
			cout << "Total cost : " << dist[Start][End] << endl << endl;
		}
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: