HDU 2680 Choose the best route

传送门

最短路。
很简单的一道多起点的求最短路的问题,注意是有向边,会有重边。

当然我看到了我自己两年前写的版本是把图倒过来,终点当作起点,起点当作终点,每条边都取反向,从原终点开始dijkstra,然后看看哪个原起点的d最小。。。

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

const int MAXN = 1001;
const int INF = 1e9;
int N, M, T;

struct Edge
{
	int n;
	int w;
};
vector<Edge> ve;
vector<int> v[MAXN];
bool vis[MAXN];
int d[MAXN];

void init()
{
	ve.clear();
	for (int i = 0; i <= N; ++i)
		v[i].clear();
	memset(vis, 0, sizeof vis);
	fill(d, d + MAXN, INF);
}

void dijkstra(int s)
{
	d[s] = 0;
	for (int i = 0; i <= N; ++i)
	{
		int u = -1, mind = INF;
		for (int j = 0; j <= N; ++j)
		{
			if (!vis[j] && d[j] < mind)
			{
				mind = d[j];
				u = j;
			}
		}
		if (u == -1) return;
		vis[u] = true;
		for (int j = 0; j < v[u].size(); ++j)
		{
			int n = ve[v[u][j]].n;
			int w = ve[v[u][j]].w;
			if (!vis[n] && d[u] + w < d[n])
				d[n] = d[u] + w;
		}
	}
}

int main()
{
	int a, b, c;
	for (; ~scanf("%d%d%d", &N, &M, &T);)
	{
		init();
		for (int i = 0; i < M; ++i)
		{
			scanf("%d%d%d", &a, &b, &c);
			ve.push_back(Edge{ b,c });      // 有向边
			v[a].push_back(i);
		}
		scanf("%d", &a);
		for (; a--;)
		{
			scanf("%d", &b);
			ve.push_back(Edge{ b,0 });
			v[0].push_back(ve.size() - 1);  // 多个起点连接虚拟起点
		}

		dijkstra(0);
		printf("%d\n", d[T] != INF ? d[T] : -1);
	}

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