【UVA10537】The Toll! Revisited (逆推最短路)

题目:

Sample Input
1
a Z
19 a Z
5
A D
D X
A b
b c
c X
39 A X
-1
Sample Output
Case 1:
20
a-Z
Case 2:
44
A-b-c-X

题意:

  有两种节点,一种是大写字母,一种是小写字母。首先输入m条边,当经过小写字母时需要付一单位的过路费,当经过大写字母时,要付当前财务的1/20做过路费(向上取整)。问在起点最少需要带多少物品使到达终点时还有k个物品。当有多条符合条件的路径时输出字典序最小的一个。

分析:

  逆推进行最短路,输出时顺序输出并选择最小字典序即可。(超级讨厌字符输入有没有,TAT,RE好多遍,记得要long long)

代码如下:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<queue>
  8 using namespace std;
  9 #define Maxn 10100
 10 #define LL long long
 11 
 12 int s,e;
 13 
 14 struct node
 15 {
 16     int x,y,next;
 17 }t[2*10*Maxn];int len;
 18 
 19 int first[Maxn];
 20 LL dis[Maxn];
 21 bool inq[Maxn];
 22 
 23 queue<int > q;
 24 
 25 void ins(int x,int y)
 26 {
 27     t[++len].x=x;t[len].y=y;
 28     t[len].next=first[x];first[x]=len;
 29 }
 30 
 31 int mymin(int x,int y) {return x<y?x:y;}
 32 
 33 void spfa(int s,int w)
 34 {
 35     memset(dis,127,sizeof(dis));
 36     memset(inq,0,sizeof(inq));
 37     while(!q.empty()) q.pop();
 38     dis[s]=w;inq[s]=1;q.push(s);
 39     while(!q.empty())
 40     {
 41         int x=q.front();q.pop();inq[x]=0;
 42         LL now;
 43         if(x>26) now=dis[x]+1;
 44         else now=(LL)ceil(dis[x]*1.0*20/19);
 45         for(int i=first[x];i;i=t[i].next)
 46         {
 47             int y=t[i].y;
 48             if(dis[y]>now)
 49             {
 50                 dis[y]=now;
 51                 if(!inq[y])
 52                 {
 53                     q.push(y);
 54                     inq[y]=1;
 55                 }
 56             }
 57         }
 58     }
 59 }
 60 
 61 void pri(int x)
 62 {
 63     if(x>26) printf("%c",x-27+'a');
 64     else printf("%c",x-1+'A');
 65     
 66 }
 67 void ffind(int x,int z)
 68 {
 69     pri(x);
 70     if(x==z) return;printf("-");
 71     int mn=100;
 72     LL a,b;
 73     a=dis[x]-1;
 74     b=dis[x]-(LL)ceil(dis[x]*1.0/20);
 75     for(int i=first[x];i;i=t[i].next)
 76     {
 77         int y=t[i].y;
 78         if(y==x) continue;
 79         LL now;
 80         if(y<=26) now=b;
 81         else now=a;
 82         if(now==dis[y]) mn=mymin(mn,y);
 83     }
 84     if(mn<100) ffind(mn,z);
 85 }
 86 
 87 int main()
 88 {
 89     int n,kase=0;
 90     while(1)
 91     {
 92         scanf("%d",&n);getchar();
 93         if(n==-1) break;
 94         char a,b,c;
 95         int x,y;
 96         memset(first,0,sizeof(first));
 97         len=0;
 98         for(int i=1;i<=n;i++)
 99         {
100             scanf("%c%c%c",&a,&c,&b);getchar();
101             if(a>='a'&&a<='z') x=a-'a'+27;
102             else x=a-'A'+1;
103             if(b>='a'&&b<='z') y=b-'a'+27;
104             else y=b-'A'+1;
105             ins(x,y);ins(y,x);
106         }
107         int p;scanf("%d%c%c%c%c",&p,&c,&a,&c,&b);getchar();
108         if(a>='a'&&a<='z') x=a-'a'+27;
109         else x=a-'A'+1;
110         if(b>='a'&&b<='z') y=b-'a'+27;
111         else y=b-'A'+1;
112         spfa(y,p);
113         printf("Case %d:
",++kase);
114         printf("%lld
",dis[x]);
115         ffind(x,y);printf("
");
116     }
117     return 0;
118 }
[UVA10537]

2016-04-06 13:35:13

原文地址:https://www.cnblogs.com/Konjakmoyu/p/5358993.html