题意:给定一些有向边,以及一个目的地,从某个点到达目的地,再从目的地回到那个点。共有n个点,问这n个点花费最大是多少?
思路:从目的地回去直接把目的地作为源点即可。那么从某个点到达目的地应该如何得到最小花费?假设1-2-3,3作为目的地,可以看做3-2-1,即把所有边逆转,以目的地作为源点,即可求得所有点到目的地的最短距离。
AC代码
#include <cstdio> #include <cmath> #include <cctype> #include <algorithm> #include <cstring> #include <utility> #include <string> #include <iostream> #include <map> #include <set> #include <vector> #include <queue> #include <stack> using namespace std; #pragma comment(linker, "/STACK:1024000000,1024000000") #define eps 1e-10 #define inf 0x3f3f3f3f #define PI pair<int, int> typedef long long LL; const int maxn = 1000 + 5; int d1[maxn], d2[maxn], vis[maxn]; int n, m, goal; vector<int>G[maxn]; struct Edge{ int from, to, dist; Edge() {} Edge(int u, int v, int d):from(u), to(v), dist(d){} }; vector<Edge>edges, rever; void add_eage(int u, int v, int cost) { edges.push_back(Edge(u, v, cost)); int m = edges.size(); G[u].push_back(m-1); } struct node{ int d, u; node(){} node(int d, int u):d(d), u(u){} bool operator < (const node &p) const { return d > p.d; } }; void dijkstra(int s, int d[]) { priority_queue<node>q; d[s] = 0; memset(vis, 0, sizeof(vis)); q.push(node(0, s)); while(!q.empty()) { node p = q.top(); q.pop(); int u = p.u; if(vis[u]) continue; vis[u] = 1; for(int i = 0; i < G[u].size(); ++i) { Edge &e = edges[G[u][i]]; if(d[u] + e.dist < d[e.to]) { d[e.to] = d[u] + e.dist; q.push(node(d[e.to], e.to)); } } } } void init() { for(int i = 1; i <= n; ++i) G[i].clear(); edges.clear(); } int main() { while(scanf("%d%d%d", &n, &m, &goal) == 3) { init(); int u, v, cost; rever.clear(); for(int i = 0; i < m; ++i) { scanf("%d%d%d", &u, &v, &cost); rever.push_back(Edge(v, u, cost)); add_eage(u, v, cost); } memset(d1, inf, sizeof(d1)); dijkstra(goal, d1); init(); for(int i = 0; i < rever.size(); ++i) { int u = rever[i].from, v = rever[i].to, cost = rever[i].dist; add_eage(u, v, cost); } memset(d2, inf, sizeof(d2)); dijkstra(goal, d2); int ans = 0; for(int i = 1; i <= n; ++i) { ans = max(d1[i]+d2[i], ans); } printf("%d\n", ans); } return 0; }
如有不当之处欢迎指出!