Uva 10537 过路费(加强版) (Dijkstra)
2015-06-22 21:27
288 查看
n条边的无向图,由起点向终点运送货物。每进入一个村庄需要缴纳1个货物,进入一个城镇每20单位货物需要缴纳1个货物。
求过路费最少的路线。
从终点逆向用一次Dijkstra就好了。
问题的关键是路径的花费cast的计算。由A到B,若B是村庄,则cast=1,若B是城镇,则cast=(d[B]+18)/19。
设d[u]为进入城镇后最少需要的货物数量。
因为d[A]-(d[A]/20+(d[A]%20!=0))=d[A]-(d[A]+19)/20=d[B] ,即有 d[A]=20*(d[B]+18)/19, cast=d[A]-d[B]=(d[B]+18)/19
求过路费最少的路线。
从终点逆向用一次Dijkstra就好了。
问题的关键是路径的花费cast的计算。由A到B,若B是村庄,则cast=1,若B是城镇,则cast=(d[B]+18)/19。
设d[u]为进入城镇后最少需要的货物数量。
因为d[A]-(d[A]/20+(d[A]%20!=0))=d[A]-(d[A]+19)/20=d[B] ,即有 d[A]=20*(d[B]+18)/19, cast=d[A]-d[B]=(d[B]+18)/19
#include<bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f3f3f3f3f #define maxn 55 typedef long long LL; struct HeapNode{ //优先队列结点 LL d; int u; bool operator < (const HeapNode& rhs) const{ return d>rhs.d; } }; struct Edge{ //边 int from,to,dist; }; LL P; struct Dijkstra{ int n,m; //点数和边数 vector<Edge> edges; //边列表 vector<int> G[maxn]; //每个结点出发的边编号(从0开始) bool done[maxn]; //是否已永久标号 LL d[maxn]; //s到各个点的距离 int p[maxn]; //最短路中的上一条边 void init(int n){ this->n=n; for(int i=0;i<=n;++i) G[i].clear();//清空邻接表 edges.clear();//清空边表 } void addEdge(int from,int to,int dist){ edges.push_back((Edge){from,to,dist}); m=edges.size(); G[from].push_back(m-1); } void dijkstra(int s){ //求s到所有点的最短距离 priority_queue<HeapNode> Q; for(int i=0;i<=n;++i) d[i]=INF; d[s]=P; memset(done,0,sizeof(done)); Q.push((HeapNode){P,s}); while(!Q.empty()){ HeapNode x=Q.top();Q.pop(); int u=x.u; if(done[u]) continue; done[u]=1; for(int i=0;i<G[u].size();++i){ Edge e=edges[G[u][i]]; LL cast; if(u<26) cast=(d[u]+18LL)/19LL; else cast=1; if(d[e.to]>d[u]+cast){ d[e.to]=d[u]+cast; p[e.to]=u; Q.push(HeapNode{d[e.to],e.to}); } else if(d[e.to]==d[u]+cast&&p[e.to]>p[u]){ p[e.to]=u; Q.push(HeapNode{d[e.to],e.to}); } } } } void output(int s,int e,vector<int>& path){ int pos=s; while(1){ path.push_back(pos); if(pos==e) break; pos=p[pos]; } } }; int toint(char x){ if(x>='A'&&x<='Z') return x-'A'; else return x-'a'+26; } int main() { int ca=1,n,m,i,j,x,y,z; char a,b; while(~scanf("%d",&n)&&n!=-1) { Dijkstra D; D.init(maxn-1); for(i=1;i<=n;++i){ cin>>a>>b; x=toint(a),y=toint(b); D.addEdge(x,y,0); D.addEdge(y,x,0); } scanf("%lld %c %c",&P,&a,&b); printf("Case %d:\n",ca++); D.dijkstra(toint(b)); printf("%lld\n",D.d[toint(a)]); vector<int> path; D.output(toint(a),toint(b),path); for(i=0;i<path.size()-1;++i) if(path[i]<26) printf("%c-",path[i]+'A'); else printf("%c-",path[i]+'a'-26); if(path[i]<26) printf("%c\n",path[i]+'A'); else printf("%c\n",path[i]+'a'-26); } return 0; }
相关文章推荐
- 第二次冲刺团队进展报告五
- C#获取根目录的方法集合
- 20 个强大的 Sublime Text 插件
- 经典范例:文件的复制
- Ubuntu 安装 Redis
- 英语的原理∶用美国人的思维学英语
- 第二次冲刺团队进展报告四
- Sublime Text 3 常用插件以及安装方法
- 二维数组求和
- [.NET领域驱动设计实战系列]专题九:DDD案例:网上书店AOP和站点地图的实现
- 第二次冲刺团队进展报告三
- 最好的Sublime Text插件集合
- Single Image Haze Removal(图像去雾)-CVPR’09 Best Paper
- STL之string插入
- 两个栈实现一个队列
- 端口扫描-调用NC扫描
- 第二次冲刺团队进展报告二
- 读Pyqt4教程,带你入门Pyqt4 _012
- 内存对齐的那点事
- [leetcode] 85.Maximal Rectangle