最短路。
很简单的一道多起点的求最短路的问题,注意是有向边,会有重边。
当然我看到了我自己两年前写的版本是把图倒过来,终点当作起点,起点当作终点,每条边都取反向,从原终点开始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;
}