2019 西安ACM-ICPC 邀请赛 M 题 Travel

M.Travel

原题网址

这题是单源最短路的变形,题中需要维护两个量,到达结点i的步数,到达结点i的等级。用dijikstra 算法时每个节点先比较飞船等级,保留较低等级。等级相同再比较到达i的步数,保留步数较少的。最后更新i处的值。我在这使用cla[100005] ,dis[100005]维护i处的飞船等级和到达i的步数。
注意dijikstra算法要优化,否则超时。可以定义结构体,重载运算符,再用priority_queue优化。
代码如下:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
#include <sstream>
#define INF 107801
#define MAXN 2e5+9
#define __maxNodes 1005
const long long mod=1e6+3;
using namespace std;
struct Edge{
    int from,to;
    int w;
};
vector<Edge> vec[100005];
int n,m;
int dis[100005],vis[100005];
//int cp[100005];
int cla[100005];
int d,c1,e;
int ans;
struct point{
    int u;
    bool operator < (const point op) const{
        if(cla[u]>cla[op.u]) return true;
        else if(cla[u]==cla[op.u] && dis[u]>dis[op.u]) return true;
        else return false;
    }
};
priority_queue<point> q;
void dijk()
{
    while (!q.empty())
    {
        point we=q.top(); q.pop();//cout << we.u << endl;
        for(int i=0;i<vec[we.u].size();i++)
        {
            Edge ed=vec[we.u][i];
            int c,st=we.u;
            if(vis[ed.to]) continue;
            else
                vis[st]=1;
            if(cla[st]*d<ed.w || cla[st]*e<=dis[st])
            {
                if(cla[st]*d<ed.w)
                {
                    c=(ed.w-1)/d+1;
                }
                else
                {
                    c=cla[st]+1;
                }
            }
            else c=cla[st];

            if(c>cla[ed.to]) continue;
            else if(c==cla[ed.to] && dis[ed.to]<=dis[st]+1) continue;
            else
            {
                cla[ed.to]=c;
                dis[ed.to]=dis[st]+1;
            }
            point ne;//cout << ne.u << endl;
            ne.u=ed.to;
            q.push(ne);
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    int i;
    Edge e1,e2;
    for(i=0;i<=n;i++)
        vec[i].clear();
    scanf("%d%d%d",&c1,&d,&e);
    for(i=0;i<m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        e1.from=x;e1.to=y;e1.w=z;
        e2.from=y;e2.to=x;e2.w=z;
        vec[x].push_back(e1);
        vec[y].push_back(e2);
    }
    //ans=INF;
    memset(dis,INF,sizeof(dis));
    memset(vis,0,sizeof(vis));
    memset(cla,INF,sizeof(cla));
    //cout << dis[0] << endl;
    dis[1]=0;cla[1]=0;vis[1]=1;
    point s;s.u=1;q.push(s);
    dijk();
    //dfs(1,n);
    printf("%d\n",cla[n]*c1);
    return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值