uva 10537 Toll! Revisited(优先队列优化dijstra及变形)

Toll! Revisited

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

思路:已知终点的权值,那么可以从终点向前推。求终点到起点的最短路径,然后按字典序打印路径。

比较难处理的是:向前推时前驱节点的权值计算。列个方程算算就可以了,主要时不能整除的情况。

计算前驱结点dis值的时候,同时记录(i,j)的边权值,这是打印路径的依据。

#include <stdio.h>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <math.h>
#include <string.h>
#include <stack>
#include <queue>
#define LL long long
#define _LL __int64

using namespace std;
const int INF = 0x3f3f3f3f;
const int maxm = 1010;
const int maxn = 60;

struct node
{
    int v,w;
    int next;
}edge[maxm];

int m;
int pre[maxn],cnt;
int start,end;
LL dis[maxn],p;
int vis[maxn];
vector <int> ans;

void init()
{
    cnt = 0;
    memset(pre,-1,sizeof(pre));
    for(int i = 0; i < maxm; i++)
        edge[i].w = 0;
}

void add(int u, int v)
{
    edge[cnt].v = v;
    edge[cnt].next = pre[u];
    pre[u] = cnt++;
}

void dijstra()
{
    priority_queue <pair<LL,int>, vector<pair<LL,int> >, greater<pair<LL,int> > > que;
    while(!que.empty()) que.pop();
    memset(dis,INF,sizeof(dis));
    memset(vis,0,sizeof(vis));

    dis[end] = p;

    que.push(make_pair(dis[end],end));

    while(!que.empty())
    {
        int u = que.top().second;
        que.pop();
        if(vis[u]) continue;
        vis[u] = 1;

        for(int i = pre[u]; i != -1; i = edge[i].next) //松弛相邻节点
        {
            if(vis[edge[i].v]) continue;
            int v = edge[i].v;

            if(u < 26)
            {
                //计算前驱结点的权值,判断是否整除,若不整除,尝试加1继续判断
                if(dis[u]%19 == 0)
                {
                    if(dis[v] > dis[u]/19*20)
                    {
                        dis[v] = dis[u]/19*20;
                        edge[i].w = edge[i^1].w = dis[v]-dis[u];
                        que.push(make_pair(dis[v],v));
                    }
                }
                else if( (dis[u]+1)%19 )
                {
                    if(dis[v] > (dis[u]+1)*20/19)
                    {
                        dis[v] = (dis[u]+1)*20/19;
                        edge[i].w = edge[i^1].w = dis[v]-dis[u];
                        que.push(make_pair(dis[v],v));
                    }
                }
                else
                {
                    if(dis[v] > (dis[u]+1)*20/19-1 )
                    {
                        dis[v] = (dis[u]+1)*20/19-1;
                        edge[i].w = edge[i^1].w = dis[v]-dis[u];
                        que.push(make_pair(dis[v],v));
                    }
                }
            }
            else
            {
                if(dis[v] > dis[u]+1)
                {
                    dis[v] = dis[u]+1;
                    edge[i].w = edge[i^1].w = 1;
                    que.push(make_pair(dis[v],v));
                }
            }

        }
    }
}

void solve()
{
    ans.clear();
    int now;
    now = start;
    ans.push_back(now);
    while(now != end)
    {
        int tmp = 1<<6;
        for(int i = pre[now]; i != -1; i = edge[i].next)
        {
            int v = edge[i].v;
            //因为输出字典序最小的,所以求出满足dis[now] - dis[v] == edge[i].w中最小的v
            if(dis[now] - dis[v] == edge[i].w && v < tmp)
            {
                tmp = v;
            }
        }
        ans.push_back(tmp);
        now = tmp;
    }

    printf("%c",ans[0]+‘A‘);

    for(int i = 1; i < (int)ans.size(); i++)
        printf("-%c",ans[i]+‘A‘);
    printf("\n");
}
int main()
{
    int item = 1;
    char t1,t2;
    while(~scanf("%d",&m))
    {
        if(m == -1) break;
        init();
        getchar();
        for(int i = 0; i < m; i++)
        {
            scanf("%c %c",&t1,&t2);
            getchar();
            add(t1-‘A‘,t2-‘A‘);
            add(t2-‘A‘,t1-‘A‘);
        }

        scanf("%lld %c %c",&p,&t1,&t2);
        start = t1-‘A‘;
        end = t2-‘A‘;

        dijstra();
        printf("Case %d:\n",item++);
        printf("%lld\n",dis[start]);
        solve();
    }
    return 0;
}

uva 10537 Toll! Revisited(优先队列优化dijstra及变形)

时间: 2024-10-11 18:47:26

uva 10537 Toll! Revisited(优先队列优化dijstra及变形)的相关文章

UVA 11374 Airport Express(优先队列优化dijstra + 枚举)

UVA Airport Express 题意:在Iokh市机场快线分为经济线和商业线.线路和速度价格都不同.你只有一张商业线车票,即最多只能坐一站商业线,其他时候只能坐经济线.找出一条去机场最快的线路. 思路:因为商业线只能坐一站,假如乘坐一条商业线(a,b),那么起点到a,b到终点都必须是最短路.所以先预处理起点和终点到其他所有点的最短路,分别记为f()和g(),两次dijstra即可.那么我们只需枚举每条商业线求出所有的f(a)+T(a,b)+g(b)然后求最小即可. 1w是TLE,改成了优

UVA 10537 - The Toll! Revisited(dijstra扩展)

UVA 10537 - The Toll! Revisited 题目链接 题意:给定一个无向图,大写字母是城市,小写字母是村庄,经过城市交过路费为当前货物的%5,路过村庄固定交1,给定起点终点和到目标地点要剩下的货物,问最少要带多少货物上路,并输出路径,如果有多种方案,要求字典序最小 思路:dijstra的逆向运用,d数组含义变成到该结点至少需要这么多货物,然后反向建图,从终点向起点反向做一遍 这题被坑了..并不是输出的城市才存在,比如下面这组样例 0 1 A A 应该输出 1 A 代码: #i

UVA - 10537 The Toll! Revisited (最短路变形逆推)

Description Problem G Toll! Revisited Input: Standard Input Output: Standard Output Time Limit: 1 Second Sindbad the Sailor sold 66 silver spoons to the Sultan of Samarkand. The selling was quite easy; but delivering was complicated. The items were t

PriorityQueue+Dijkstra优先队列优化的Dijstra

前面分别介绍了"原生的Dijkstra"即毫无优化的Dijkstra,但这种Dijkstra的效率较低为n^n,因此面对较大数据量的时候需要对其进行优化,也就是优化所采用的贪心策略的实现,因此就有了Heao+Dijkstra堆优化的Dijkstra,但是堆优化的实现很复杂,而PriorityQueue+Dijkstra优先队列优化的Dijstra的效率虽然略低于堆优化的Dijkstra,但是实现却容易的多,也不容易出错,因为可以借助java类库中的PriorityQueue来实现,因此

UVA 10537最小树(逆向+字典序输出)

The Toll! Revisited Sindbad the Sailor sold 66 silver spoons to the Sultan of Samarkand. The selling was quite easy; but delivering was complicated. The items were transported over land, passing through several towns and villages. Each town and villa

HDU - 3790 最短路径问题(Dijkstra+优先队列优化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3790 题意:中文题(边被赋予两种属性,一种是路径,一种是花费),然后略.(逃...... 今天看了卿学姐的视频,初尝SPFA和Dijkstra. 一个是用队列优化,一个是用优先队列优化.这道题目用这两种方法都可以. dijkstra算法思想(贪心):从距离起点最近的点开始,从这个点遍历一遍它周围的点,进行松弛操作,直到最终点. 整个的算法思想就是贪心,每次都给它形成最短路. 这道题目值得注意的是预处

地铁 Dijkstra(优先队列优化) 湖南省第五届省赛

传送门:地铁 思路:拆点,最短路:拆点比较复杂,所以对边进行最短路,spfa会tle,所以改用Dijkstra(优先队列优化) 模板 /************************************************************** Problem: User: youmi Language: C++ Result: Accepted Time: Memory: *****************************************************

Vijos 1243 生产产品 (优先队列优化的动态规划)

题意:中文题.不说了. 注意一些地方,机器的执行过程是没有顺序的,而且每个机器可以用多次.第一次执行的机器不消耗转移时间K. 用dp[i][j]表示第i个机器完成第j个步骤的最短时间,sum[j][i]表示第i个机器完成前j个步骤的时间. 比较容易想到一个朴素的状态转移方程: dp[i][j]=min{dp[k][j']+sum[j][i]-sum[j'][i]}+K  (j-j'<l),(i!=k) 这里状态是O(n*m),转移是O(n*l),一定会超时,需要优化. 方程变形得dp[i][j]

最短路--dijkstra+优先队列优化模板

不写普通模板了,还是需要优先队列优化的昂 1 #include<stdio.h> //基本需要的头文件 2 #include<string.h> 3 #include<queue> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 typedef pair<int,int> pii; 8 const int INF=0x3f3f3f3f; 9 10 11