UVA 10537 最短路

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;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值