HDU3499Flight(双向Dijkstra)
来源:互联网 发布:python 面部表情识别 编辑:程序博客网 时间:2024/06/05 15:45
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3499
题意:
有一个有向图,你要从特定的城市A飞到城市B去.给你这个图的所有边(航班)信息.但是你手上有一张卡,可以使得某一趟航班的价格减半.现在的问题是你从A到B的最小费用是多少?
分析:
首先要知道这条如果让一条原本是最短路径(假设总距离为x)上最长的边变成半价,最终求得的解不一定是最优的。因为假如现在有另外一条路径,假设该路径距离为x+1。且这条路径上只有5条边,4条长为1的边,但是1条长为x-3的边。如果我们让这条路径的x-3边变成半价是不是能得到更好的结果?
明显必须从m条边中枚举那条半价的航班.假设这条半价的航班是i->j的.那么我们必须知道从A到i的最短距离和从j到B的最短距离. 从A到i的最短距离可以通过求A的单源最短路径即可.从j(j有可能是任意点)到B的最短距离必须建立原图的反向图,然后求B到其他所有点的单源最短路径.(想想是不是)
原题输入数据很多,需要用邻接表的dijkstra算法且距离要用long long保存
结构体封装代码:
#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<queue>#include<map>using namespace std;const long long INF = 1e17;const int maxn = 100005;const int maxm = 500005;int n, m;map<string, int> mp;struct Edge{ int form, to, next; long long dist; Edge(){} Edge(int _form, int _to, long long _dist):form(_form), to(_to), dist(_dist){} Edge(int _form, int _to, long long _dist, int _next):form(_form), to(_to), dist(_dist), next(_next){}}edge[maxm];struct HeapNode{ long long d; int u; HeapNode(){} HeapNode(int _u, long long _d):u(_u), d(_d){}; bool operator < (const HeapNode &other) const { return d > other.d; }};struct Dijkstra{ int n, m, head[maxm]; Edge edge[maxm]; long long dis[maxn]; void init() { m = 0; memset(head, -1, sizeof(head)); } void add_edge(int from, int to, long long dist) { edge[m] = Edge(from, to, dist, head[from]); head[from] = m++; } void dijkstra(int s) { priority_queue<HeapNode> q; for(int i = 0; i < n; i++) dis[i] = i == s ? 0 : INF; q.push(HeapNode(s, dis[s])); while(!q.empty()) { HeapNode x = q.top(); q.pop(); int u = x.u; for(int i = head[u]; i != -1; i = edge[i].next) { if(dis[edge[i].to] > dis[u] + edge[i].dist) { dis[edge[i].to] = dis[u] + edge[i].dist; q.push(HeapNode(edge[i].to, dis[edge[i].to])); } } } }}dj1, dj2;int getid(string s){ if(mp.find(s) == mp.end()) mp[s] = n++; return mp[s];}int main(){ int u, v; long long w; while(scanf("%d%d", &n, &m) != EOF) { n = 0; mp.clear(); string s1, s2; dj1.init();dj2.init(); for(int i = 0; i < m ; i++) { cin >> s1 >> s2 >> w; u = getid(s1); v = getid(s2); dj1.add_edge(u, v, w); dj2.add_edge(v, u, w); edge[i] = Edge(u, v, w); } cin >> s1 >> s2; int st = getid(s1), ed = getid(s2); dj1.n = dj2.n = n; dj1.dijkstra(st), dj2.dijkstra(ed); if(dj1.dis[ed] == INF) { printf("-1\n"); continue; } long long ans = INF; for(int i = 0; i < m; i++) { int u = edge[i].form, v = edge[i].to; long long w = edge[i].dist; if(ans > dj1.dis[u] + dj2.dis[v] + w / 2) ans = dj1.dis[u] + dj2.dis[v] + w / 2; } printf("%I64d\n", ans); } return 0;}
二维数组代码:
#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<queue>#include<map>using namespace std;const int maxm = 500005;const int maxn = 100005;const long long INF = 1e17;struct Edge{ int u, v, next; long long w; Edge(){} Edge(int _u, int _v, long long _w, int _next):u(_u), v(_v), w(_w), next(_next){}}edge[2][maxm];struct HeapNode{ long long d; int u; HeapNode(int _u, long long _d):u(_u), d(_d){} bool operator < (const HeapNode &other)const { return d > other.d; }};int n, m, head[2][maxn];long long dis[2][maxn];map<string, int> mp;int getid(string s){ if(mp.find(s) == mp.end()) mp[s] = n++; return mp[s];}void Dijkstra(int flag, int s){ for(int i = 0; i < n; i++) dis[flag][i] = INF; dis[flag][s] = 0; priority_queue<HeapNode> q; q.push(HeapNode(s, dis[flag][s])); while(!q.empty()) { HeapNode now = q.top(); q.pop(); for(int i = head[flag][now.u]; i != -1; i = edge[flag][i].next) { int to = edge[flag][i].v; if(dis[flag][to] > dis[flag][now.u] + edge[flag][i].w) { dis[flag][to] = dis[flag][now.u] + edge[flag][i].w; q.push(HeapNode(to, dis[flag][to])); } } }}int main(){ while(scanf("%d%d", &n, &m) != EOF) { n = 0; string s1, s2; mp.clear(); memset(head, -1, sizeof(head)); memset(dis, 63, sizeof(dis)); for(int i = 0; i < m; i++) { long long w; cin >> s1 >> s2 >> w; int u = getid(s1), v = getid(s2); edge[0][i] = Edge(u, v, w, head[0][u]); head[0][u] = i; edge[1][i] = Edge(v, u, w, head[1][v]); head[1][v] = i; } cin >> s1 >> s2; int st = getid(s1), ed = getid(s2); Dijkstra(0, st); Dijkstra(1, ed); if(dis[0][ed] == INF) { printf("-1\n"); continue; } long long ans = INF; for(int i = 0; i < m; i++) { int u = edge[0][i].u, v = edge[0][i].v; long long dist = edge[0][i].w; if(ans > dis[0][u] + dis[1][v] + dist / 2) ans = dis[0][u] + dis[1][v] + dist / 2; } printf("%I64d\n", ans); } return 0;}
0 0
- HDU3499Flight(双向Dijkstra)
- POJ 3268 双向Dijkstra
- poj 3268 双向dijkstra
- PKU3268Silver Cow Party-双向dijkstra
- c++ 下实现多线程的双向dijkstra算法
- POJ 3159 Candies 解题报告(Dijkstra & SPFA) 及 双向Dijkstra性能测试
- dijkstra
- dijkstra
- Dijkstra
- Dijkstra
- DIJKSTRA
- DIJKSTRA
- Dijkstra
- dijkstra
- dijkstra
- Dijkstra
- Dijkstra
- Dijkstra
- JTable简单介绍,以及tableModel的使用
- mysql中having和where的区别
- bug日记2016.12.01
- 验证码识别打码程序接口示例
- QT设置程序图标
- HDU3499Flight(双向Dijkstra)
- String和StringBuilder和StringBuffer三兄弟
- Tomcat 生产服务器性能优化
- nullptr和NULL的区别
- 发送RTP封装的g711流,并用VLC接收的注意事项
- openstack网络节点的迁移
- WinCE学习路线
- [编程题] 买苹果
- Eigen复矩阵的使用[微记]