2016年清华软院保研机试第2题(最短路)

机考题二

• 40 分, LeetCode medium 档次

• 从控制台输入n+1 行,前n 行每行3 个整数,形如“A B d”,表示从节点A 到节点B 距离为d(双向)。第n+1 行形如“A B”,表示求A 到B 的最短距离。输出此最短距离。

• 例如:

1 42 3
42 789 4
1 789 9
1 789

输出

7

• BFS、动态规划、剪枝、图

--------------------------------------------------------------------------------

思路

没有看懂南大同学提示里写的“BFS、动态规划、剪枝”是什么意思,也看到一篇博文说是用0-1规划做的,不是很懂(求教)?

我的做法是首先把输入的节点的编号存到一个数组vset中,再将vset排序,然后排好序的vset去重得到n个不重复的节点,重新映射到编号0~n-1,然后再用标准的Dijkstra解一个最短路问题。

记图的节点个数为n,边条数为m(记号与题面中不一样),节点重编号复杂度O(mlogm),Dijkstra复杂度为O(n^2),如果认为m~n^2的话,总的复杂度就是O(mlogm) = O(mlogn)。

--------------------------------------------------------------------------------

代码

#include<cstdio>
#include<map>
#include<algorithm>

const int MMAX = 10005, NMAX = 105, INF = 0x3f3f3f3f;
int v1[MMAX] = {}, v2[MMAX] = {}, L[MMAX] = {};
int vset[MMAX] = {};
int d[NMAX] = {};
bool vis[NMAX] = {};
int mat[NMAX][NMAX] = {};

int dijkstra(int src, int dst, int n)
{
	int i, j, minv = INF, minid = src;
	for (i=0; i<n; i++)
	{
		if (i == src)
		{
			d[i] = 0;
		}
		else if (mat[src][i])
		{
			d[i] = mat[src][i];
		}
		else
		{
			d[i] = INF;
		}
	}
	for (j=0; j<n; j++)
	{
		minv = INF;
		for (i=0; i<n; i++)
		{
			if (!vis[i] && d[i] < minv)
			{
				minv = d[i];
				minid = i;
			}
		}
		vis[minid] = 1;
		if (minid == dst)
		{
			break;
		}
		for (i=0; i<n; i++)
		{
			if (!vis[i])
			{
				if (mat[minid][i])
				{
					d[i] = std::min(mat[minid][i] + minv, d[i]);
				}
			}
		}
	}
	return d[dst];
}


int main()
{
#ifndef ONLINE_JUDGE
	freopen("thuSE17_02.txt", "r", stdin);
#endif
	std::map<int, int> vmap;
	int i = 0, j = 0, len_vset, m, src, dst;
	while (scanf("%d%d%", &v1[i], &v2[i]) != EOF)
	{
		scanf("%d", &L[i++]);
		vset[j++] = v1[i-1];
		vset[j++] = v2[i-1];
	}
	m = i - 1;
	len_vset = j;
	src = v1[m];
	dst = v2[m];
	i = 0;
	j = 0;
	std::sort(vset, vset+len_vset);
	vmap[vset[0]] = 0;
	for (i = 1; i < len_vset; i++)
	{
		if (vset[i] != vset[i-1])
		{
			vmap[vset[i]] = ++j;
		}
	}
	int n = j + 1;
	for (i=0; i<m; i++)
	{
		mat[vmap[v1[i]]][vmap[v2[i]]] = L[i];
		mat[vmap[v2[i]]][vmap[v1[i]]] = L[i];
	}
	src = vmap[v1[m]];
	dst = vmap[v2[m]];
	printf("%d", dijkstra(src, dst, n));
	return 0;
}

猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/82425671