UVA 12661 Funny Car Racing (Dijkstra最短路)

题意:

在一个赛车比赛中,有n 个交叉点和m 个单向道路,每条道路周期性的开启a秒,关闭b秒,通过时间是t秒, 求从S到T 的最短时间?

思路:

和正常的迪杰斯特拉一样,存的是时间,优先时间小的先弹出。

只不过在压入队列中 分情况讨论:

1.如果现在的时间能进入这条道路,并且能在道路关闭之前出来,就进入队列。

2.否则就等这条道路在开启时 在进入队列。

吐槽:

会有重边的存在,写成vector 存边就过去了= =

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#define Siz(x) (int)x.size()
using namespace std;
int n,m ,s,t,ks;
const int oo = 5e7+10;
struct Node{
    int c,d;
    bool operator < (const Node& rhs) const {
        return d > rhs.d;
    }
    Node(int c=0,int d=0):c(c),d(d){}
};
struct Edge{
    int u,v,a,b,t;
    void read(){
        scanf("%d %d %d %d %d",&u, &v, &a, &b, &t);
    }
}p;
priority_queue<Node>q;
vector <Edge>edges;
int dp[307];
vector<int>g[307];
bool vis[307];
void dij(){
    for (int i = 0; i <= n; ++i){
        vis[i] = 0;
        dp[i] = oo;
    }
    dp[s] = 0;
    while(!q.empty()) q.pop();
    q.push(Node(s,0));
    while(!q.empty()){
        Node u = q.top(); q.pop();
        int c = u.c;
        if (vis[c])continue;
        vis[c] = 1;
        for (int i = 0; i < Siz(g[c]); ++i){
            int v = g[c][i];
            Edge& e = edges[v];
            v = e.v;
            int a = e.a,b = e.b, t = e.t;
            int dd = dp[c] % (a+b);
            if (t > a) continue;
            if (dd + t > a){
                if (dp[v] > dp[c] + a+b-dd+t){
                    dp[v] = dp[c]+a+b+t-dd;
                    q.push(Node(v,dp[v]));
                }
            }
            else {
                if (dp[v] > dp[c] + t){
                    dp[v] = dp[c] + t;
                    q.push(Node(v,dp[v]));
                }
            }
        }
    }
}
int main(){
    while(~scanf("%d %d %d %d",&n ,&m, &s, &t)){
        for (int i = 0; i <= n; ++i)g[i].clear();
        edges.clear();
        for (int i = 0; i < m; ++i){
            p.read();
            int u = p.u, v = p.v;
            edges.push_back(p);
            g[u].push_back(i);
        }
        dij();
        printf("Case %d: %d\n",++ks,dp[t]);
    }
    return 0;
}
/**
3 2 1 3
1 2 5 6 3
2 3 7 7 6
3 2 1 3
1 2 5 6 3
2 3 9 5 6

Case 1: 20
Case 2: 9
**/


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值