HDU 2066 一个人的旅行

传送门

最短路,只不过有多个开始点和结束点,选一条从任意开始点到任意结束点最短的路。
再额外建立一个虚拟开始点和虚拟结束点即可。

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;

const int INF = 1e9;
const int MAXN = 1002;
int T, S, D;
int g[MAXN][MAXN];
int dis[MAXN];
bool vis[MAXN];
bool exist[MAXN];

void dijkstra(int s)
{
	dis[s] = 0;
	int counter = 0;
	for (int i = 0; i < MAXN; i++)
		if (exist[i]) counter++;
	for (int i = 0; i < counter; i++)            // exist主要就是为了减少外循环的次数,有多少点 循环多少次就够了
	{
		int u = -1, mind = INF;
		for (int j = 0; j <= 1001; j++)
		{
			if (!vis[j] && exist[j] && dis[j] < mind)      // 这处的exist其实没什么用
			{
				mind = dis[j];
				u = j;
			}
		}
		vis[u] = 1;
		for (int j = 0; j <= 1001; j++)
		{
			if (!vis[j] && exist[j] && g[u][j] != -1)      // 这处的exist其实没什么用
			{
				if (dis[u] + g[u][j] < dis[j])
					dis[j] = dis[u] + g[u][j];
			}
		}
	}
}

int main()
{
	int a, b, c;
	for (; ~scanf("%d%d%d", &T, &S, &D);)
	{
		memset(g, -1, sizeof g);
		memset(vis, 0, sizeof vis);
		fill(dis, dis + MAXN, INF);
		memset(exist, 0, sizeof exist);
		for (; T--;)
		{
			scanf("%d%d%d", &a, &b, &c);
			exist[a] = true;
			exist[b] = true;
			if (g[a][b] == -1) g[a][b] = g[b][a] = c;
			else g[a][b] = g[b][a] = min(g[a][b], c);
		}
		for (; S--;)
		{
			scanf("%d", &a);
			g[0][a] = g[a][0] = 0;
			exist[0] = true;
		}
		for (; D--;)
		{
			scanf("%d", &a);
			g[1001][a] = g[a][1001] = 0;
			exist[1001] = true;
		}
		dijkstra(0);
		printf("%d\n", dis[1001]);
	}

    return 0;
}
posted @ 2019-03-23 16:02  CrossingOver  阅读(182)  评论(0编辑  收藏  举报