最短路 || 分层图最短路
Posted pinkglightning
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最短路 || 分层图最短路相关的知识,希望对你有一定的参考价值。
在对可以任选的一部分边或点有限制的时候,可以建分层图
HDU 3499
题意:n个城市有m条价格不同的航线,从s到t,可以选择一条边价格减半,求最小花费
建两层图,每一层图里连边,两层图里连边
#include <map> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; const int maxn = 200010; const int maxm = 1500100; const LL INF = 1000000000100LL; map<string, int> mp; int head[maxn], nxt[maxm], tot; int vis[maxn]; LL dis[maxn]; struct Edge { int t; LL d; Edge () {} Edge(int t, LL d) : t(t), d(d) {}; } l[maxm]; void build(int f, int t, LL d) { l[++tot] = Edge(t, d); nxt[tot] = head[f]; head[f] = tot; } void init() { tot = 0; memset(head, -1, sizeof(head)); mp.clear(); } struct node { int u; LL d; node () {} node(int u, LL d) : u(u), d(d) {}; bool operator < (const node &a) const { return d > a.d; } }; LL dij(int s, int t) { //bool operator < (node a, node b) {return a.d > b.d; } priority_queue<node> q; for(int i = 0; i < maxn; i++) dis[i] = INF; memset(vis, 0, sizeof(vis)); dis[s] = 0LL; q.push(node(s, 0LL)); while(q.size()) { int u = q.top().u; q.pop(); if(vis[u]) continue; vis[u] = 1; for(int i = head[u]; ~i; i = nxt[i]) { int v = l[i].t; if(dis[v] > dis[u] + l[i].d) { dis[v] = dis[u] + l[i].d; q.push(node(v, dis[v])); } } } if(dis[t] == INF) return -1; return dis[t]; } int main() { int n, m; while(~scanf("%d%d", &n, &m)) { int idx = 0; init(); for(int i = 0; i < m; i++) { char str1[13], str2[13]; LL c; scanf(" %s %s %lld", str1, str2, &c); if(mp.find(str1) == mp.end()) mp[str1] = idx++; if(mp.find(str2) == mp.end()) mp[str2] = idx++; build(mp[str1], mp[str2], c); build(mp[str1]+n, mp[str2]+n, c); build(mp[str1], mp[str2]+n, c/2); } char st[13], ed[13]; scanf(" %s %s", st, ed); printf("%lld ", dij(mp[st], mp[ed]+n)); } return 0; }
DP做法
#include <map> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; const int maxn = 100010; const int maxm = 500100; const LL INF = 1000000000100LL; map<string, int> mp; int head[maxn], nxt[maxm], tot; int vis[maxn]; LL dis[maxn][2]; struct Edge { int t; LL d; Edge () {} Edge(int t, LL d) : t(t), d(d) {}; } l[maxm]; void build(int f, int t, LL d) { l[++tot] = Edge(t, d); nxt[tot] = head[f]; head[f] = tot; } void init() { tot = 0; memset(head, -1, sizeof(head)); mp.clear(); } struct node { int u; LL d; node () {} node(int u, LL d) : u(u), d(d) {}; bool operator < (const node &a) const { return d > a.d; } }; LL dij(int s, int t) { //bool operator < (node a, node b) {return a.d > b.d; } priority_queue<node> q; for(int i = 0; i < maxn; i++) dis[i][0] = dis[i][1] = INF; memset(vis, 0, sizeof(vis)); dis[s][0] = 0LL; dis[s][1] = 0LL; q.push(node(s, 0LL)); while(q.size()) { int u = q.top().u; q.pop(); if(vis[u]) continue; vis[u] = 1; for(int i = head[u]; ~i; i = nxt[i]) { int v = l[i].t; if(dis[v][0] > dis[u][0] + l[i].d) { dis[v][0] = dis[u][0] + l[i].d; q.push(node(v, dis[v][0])); } if(dis[v][1] > dis[u][0] + l[i].d/2 || dis[v][1] > dis[u][1] + l[i].d) { dis[v][1] = min(dis[u][0] + l[i].d/2, dis[u][1] + l[i].d); q.push(node(v, dis[v][1])); } } } //printf("%d %d %lld ",s,t, dis[t][0]); if(dis[t][1] == INF || s == t) return -1; return min(dis[t][0], dis[t][1]); } int main() { int n, m; while(~scanf("%d%d", &n, &m)) { int idx = 0; init(); for(int i = 0; i < m; i++) { char str1[13], str2[13]; LL c; scanf(" %s %s %lld", str1, str2, &c); if(mp.find(str1) == mp.end()) mp[str1] = idx++; if(mp.find(str2) == mp.end()) mp[str2] = idx++; build(mp[str1], mp[str2], c); } char st[13], ed[13]; scanf(" %s %s", st, ed); printf("%lld ", dij(mp[st], mp[ed])); } return 0; }
以上是关于最短路 || 分层图最短路的主要内容,如果未能解决你的问题,请参考以下文章