【UVA10537】The Toll! Revisited
2017-10-17 17:21
399 查看
题意
给定图G=(V,E),V中有两类点,一类点(A类)在进入时要缴纳1的费用,另一类点(B类)在进入时要缴纳当前携带金额的120(不足20的部分按20算)
已知起点为S,终点为T,希望在到达T时能够拥有P的金额,问一开始在S最少要携带多少金额,并求出路径(若有多条,输出字典序最小的)
从S离开时不需要缴费,进入T时需要缴费
解法
spfa变异最短路:
其实这道题的难点就在于怎么求出花费,其他的过程则和正常的spfa一模一样,至于输出路径就记一个Pre即可
考虑一条从T到S的路径,假设当前点为u,要前往的点为v,那么按u的种类分情况讨论:
如果u为A类点,那么从u前往v的花费显然是disu+1
如果u为B类点,那么从u前往v花费就是:x=disu∗2019,while(x−x+1920<disu)x++,最后的x就是从u到v的花费,不过下面的代码不是这么写的,比较鬼畜……
然后倒着做spfa即可
复杂度
O(|V|∗|E|)
代码
给定图G=(V,E),V中有两类点,一类点(A类)在进入时要缴纳1的费用,另一类点(B类)在进入时要缴纳当前携带金额的120(不足20的部分按20算)
已知起点为S,终点为T,希望在到达T时能够拥有P的金额,问一开始在S最少要携带多少金额,并求出路径(若有多条,输出字典序最小的)
从S离开时不需要缴费,进入T时需要缴费
解法
spfa变异最短路:
其实这道题的难点就在于怎么求出花费,其他的过程则和正常的spfa一模一样,至于输出路径就记一个Pre即可
考虑一条从T到S的路径,假设当前点为u,要前往的点为v,那么按u的种类分情况讨论:
如果u为A类点,那么从u前往v的花费显然是disu+1
如果u为B类点,那么从u前往v花费就是:x=disu∗2019,while(x−x+1920<disu)x++,最后的x就是从u到v的花费,不过下面的代码不是这么写的,比较鬼畜……
然后倒着做spfa即可
复杂度
O(|V|∗|E|)
代码
#include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<queue> #define Rint register int #define Lint long long int using namespace std; const Lint INF=1e18; const int E=50010; const int N=1010; struct node { int next,from,to; }t[E]; int head ,num; int Pre ,vis ; Lint dis ; int n,S,T; Lint p; queue<int> q; void add(int u,int v) { t[++num]=(node){ head[u],u,v }; head[u]=num; } Lint cal(Lint w) { Lint u,num,y; u=w%20; if( !u ) u=w/20; else u=w/20+1; num=u*20; while( w+u>num ) { y=(w+u)%20; u= !y ? (w+u)/20 : (w+u)/20+1 ; num=u*20; } return u; } void spfa() { int tmp; for(int i=1;i<=120;i++) dis[i]=INF,Pre[i]=vis[i]=0; dis[T]=p,q.push( T ); while( !q.empty() ) { tmp=q.front(),q.pop(); vis[tmp]=0; for(int i=head[tmp],x; i ;i=t[i].next) { x=t[i].to; if( tmp>=27 && ( dis[x]>dis[tmp]+1 || ( dis[x]==dis[tmp]+1 && t[Pre[x]].from>tmp ) ) ) { dis[x]=dis[tmp]+1; Pre[x]=i; if( !vis[x] ) vis[x]=1,q.push( x ); } if( tmp<=26 && ( dis[x]>dis[tmp]+cal( dis[tmp] ) || ( dis[x]==dis[tmp]+cal( dis[tmp] ) && t[Pre[x]].from>tmp ) ) ) { dis[x]=dis[tmp]+cal( dis[tmp] ); Pre[x]=i; if( !vis[x] ) vis[x]=1,q.push( x ); } } } printf("%lld\n",dis[S]); printf("%c",S-1+'A'); for(int i=t[Pre[S]].from; i ;i=t[Pre[i]].from) printf("-%c",i-1+'A'); printf("\n"); } int main() { char a[10],b[10]; int u,v,C=0; while( scanf("%d",&n)!=EOF ) { if( n==-1 ) break ; num=0; memset( head,0x0,sizeof head ); for(int i=1;i<=n;i++) { scanf("%s%s",a,b); u=a[0]-'A'+1,v=b[0]-'A'+1; add( u,v ),add( v,u ); } scanf("%lld%s%s",&p,a,b); S=a[0]-'A'+1,T=b[0]-'A'+1; printf("Case %d:\n",++C); spfa(); } return 0; }
相关文章推荐
- UVa 10537 The Toll! Revisited (最短路)
- Uva 10537 The Toll! Revisited
- uva 10537 - The Toll! Revisited (逆向思维+最短路+输出字典序最小路径)
- UVa 10537 - The Toll! Revisited
- Uva-10537-The Toll! Revisited
- UVA 10537 The Toll! Revisited(最短路变形+输出字典序最小路径)
- uva 10537 - The Toll! Revisited(最短路)
- UVA 10537 The Toll! Revisited(dijkstra输出字典序最小的路径)
- UVA 10537 The Toll! Revisited(最短路变形)
- uva 10537 - The Toll! Revisited (逆向思维最短路)
- UVA - 10537 The Toll! Revisited (最短路变形逆推)
- UVA 10537 - The Toll! Revisited(dijstra扩张)
- UVA10537[The Toll! Revisited] dijkstra/spfa 反向建图
- 【UVA10537】The Toll! Revisited (逆推最短路)
- UVA 10537 - The Toll! Revisited(dijstra扩展)
- UVA 10537 The Toll! Revisited 过路费(最短路,经典变形)
- uva 10537 The Toll! Revisited
- UVa 10537 The Toll! Revisited! Dijkstra最短路
- UVa10537 - The Toll! Revisited(dijkstra+二分)
- UVA-10537 The Toll! Revisited (dijkstra)