HDU 5360 - In Touch(最短路)

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=5361

题意:

给出n个点可以到达的点的距离差范围(l,r),和每个点的点值。n个点的位置分别为(0,1,2,3...n).

从0点出发,求出到达其他各点的最小花费,如果无法达到则输出“-1”。

思路:

dijkstra的思路,在每个点只可能标记一次最短路,所以使用一个set去记录所有点,标记了最短路的点删去。

将一个集合的点看成一个点,用一个set(可以用优先队列去实现) 去储存。取出这个点,将枚举这个点能够到达的点,更新dis,和在上一个set删点。

AC.

#include <iostream>
#include <cstdio>
#include <set>
#include <algorithm>
#include <cstring>
#include <cmath>
#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;
typedef long long ll;
const int maxn = 2e5+5;
set<int> fir;
struct node{
    int id;
    ll val;
    node(int ii, ll vv) {
        id = ii; val = vv;
    }
    bool operator < (const node &b) const {
        if(val == b.val) return id < b.id;
        return val < b.val;
    }
};
set<node> nex;

int l[maxn], r[maxn];
ll val[maxn];
ll dis[maxn];

int main()
{
    //freopen("in", "r", stdin);
    int T;
    scanf("%d", &T);
    while(T--) {
        int n;
        scanf("%d", &n);
        for(int i = 0; i < n; ++i) {
            scanf("%d", &l[i]);
        }
        for(int i = 0; i < n; ++i) {
            scanf("%d", &r[i]);
        }
        for(int i = 0; i < n; ++i) {
            scanf("%I64d", &val[i]);
        }

        fir.clear();
        nex.clear();
        memset(dis, -1, sizeof(dis));
        dis[0] = 0;

        for(int i = 1; i < n; ++i) {
            fir.insert(i);
        }

        nex.insert(node(0, val[0]));
        set<int>::iterator it, tmp;

        while(!nex.empty()) {
            node x = *nex.begin();
            nex.erase(nex.begin());
            int id = x.id;

            it = fir.lower_bound(id - r[id]);
            while(it != fir.end() && *it <= (id-l[id])) {
                dis[*it] = x.val;
                //printf("id = %d, it = %d, dis = %d\n", id, *it, dis[*it]);

                nex.insert(node(*it, dis[*it]+val[*it]));
                tmp = it++;
                fir.erase(tmp);
            }

            it = fir.lower_bound(id+l[id]);
            while(it != fir.end() && *it <= (id+r[id])) {
                dis[*it] = x.val;
                //printf("id = %d, it = %d, dis = %d\n", id, *it, dis[*it]);

                nex.insert(node(*it, dis[*it]+val[*it]));
                tmp = it++;
                fir.erase(tmp);
            }
        }

        for(int i = 0; i < n; ++i) {
            printf("%I64d", dis[i]);
            if(i < n-1) printf(" ");
            else printf("\n");
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值