UVA 10537
题目链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=17&page=show_problem&problem=1478
题意:
给一个图,图中点的编号是大写字母或者小写字母。
一个人身上带有权值。规定经过小写字母编号结点,权值-1;经过大写字母编号结点,每二十个权值减一个权值,不满二十按二十算。
先给到终点时权值,求最小的起点权值。
思路:
最短路。
三个地方出错。
1)数据范围大,一些地方爆long long
2)逆推回去时候需要遍历找到一个最小值而不能直接求出
3)逆推回去的时候是以当前结点作为权值+-的判断条件而不是以下一个点作为判断条件。
源码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <stack>
using namespace std;
#define LL long long
#define inf (1000000000000000000)
const int MAXN = 200 + 5;
int m;
int head[MAXN], cnt;
struct Edge
{
int v, ne;
Edge(){}
Edge(int _u, int _v){v = _v, ne = head[_u];}
}edge[MAXN*MAXN*2];
void add_edge(int u, int v)
{
edge[cnt] = Edge(u, v);
head[u] = cnt++;
}
struct D
{
LL d;
int u;
bool operator < (const D &rbs)const
{
return d > rbs.d;
}
};
priority_queue<D>que;
stack<int>sta;
LL dp[MAXN];
int vis[MAXN];
int path[MAXN];
void dijkstra(int s, LL p)
{
memset(vis, 0, sizeof(vis));
for(int i = 0 ; i < MAXN ; i++)
dp[i] = inf, path[i] = 1000;
dp[s] = p;
while(!que.empty()) que.pop();
que.push(D{p, s});
while(!que.empty()){
int org = que.top().u; que.pop();
// printf("org = %d\n", org);
if(vis[org]) continue;
vis[org] = 1;
for(int now = head[org] ; now != -1 ; now = edge[now].ne){
int v = edge[now].v;
LL val;
if(org <= 'Z' && org >= 'A'){
LL t1 = dp[org] / 20;
while(1){
// printf("dp[org] = %lld , t1 = %d\n", dp[org], t1);
if((dp[org] + t1 + 19LL) / 20LL == t1)
break;
t1++;
}
val = t1 + dp[org];
// val = dp[org] + (dp[org] + (LL)19) / (LL)20;
}
else
val = dp[org] + 1;
if(val < dp[v]){
path[v] = org;
dp[v] = val;
que.push(D{dp[v], v});
}
else if(val == dp[v])
path[v] = min(path[v], org);
}
}
}
char init()
{
char str[10];
scanf("%s", str);
return str[0];
}
int main()
{
// freopen("UVA 10537.in", "r", stdin);
int cas = 0;
while(scanf("%d", &m) != EOF && m != -1){
cnt = 0;
memset(head, -1, sizeof(head));
char op1, op2;
for(int i = 1 ; i <= m ; i++){
op1 = init();
op2 = init();
// printf("op1 = %c, op2 = %c\n", op1, op2);
int u, v;
u = op1;
v = op2;
// printf("u = %d, v = %d\n", u, v);
add_edge(u, v);
add_edge(v, u);
}
LL p;
int s, e;
scanf("%lld", &p);
op1 = init();
op2 = init();
s = op1, e = op2;
// printf("s = %d, e = %d\n", s, e);
// printf("s = %c, e = %c\n", toC(s), toC(e));
// system("pause");
dijkstra(e, p);
// while(!sta.empty()) sta.pop();
// int now = e;
// while(now != s)
// sta.push(now), now = path[now], printf("now = %c\n", toC(now));
printf("Case %d:\n", ++cas);
// while(!sta.empty()){
// int temp = sta.top(); sta.pop();
// if(f) f = 0;
// else printf("-");
// printf("%c", toC(temp));
// }
printf("%lld\n", dp[s]);
int now = s;
while(now != e){
printf("%c-", now);
now = path[now];
}
printf("%c\n", e);
}
return 0;
}