Codeforces786B

传送门

  • n个节点且固定起点最短路,三种加边方法
  • 1.u->v, 边权为w;2. u->[l, r], 边权为w;3. [l, r]->u, 边权为w

AC_Code

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define lson rt << 1
#define rson rt << 1 | 1
using namespace std;
typedef long long LL;

const LL INF = 0x3f3f3f3f3f3f3f3f;
const int MXN = 1e6 + 6;
const int MXE = 4e6 + 6;

int n, m, q, st;
int inde;
vector<int>vs;
struct lp{
    int v, w, nex;
    friend bool operator < (const lp &a,const lp &b) {
        return a.w > b.w;
    }
}cw[MXE], A, B;
int head[MXN], tot;
LL dis[MXN];
void add_edge(int u,int v,int w) {
    cw[++tot].v = v; cw[tot].w = w; cw[tot].nex = head[u];
    head[u] = tot;
}
int seg[MXN][2];
void build(int id,int l,int r,int rt) {
    seg[rt][id] = ++inde;
    if(l == r) {
        if(id) add_edge(seg[rt][id], l, 0);
        else add_edge(l, seg[rt][id], 0);
        return;
    }
    int mid = (l + r) >> 1;
    build(id, l, mid, lson); build(id, mid + 1, r, rson);
    if(id) {
        add_edge(seg[rt][id], seg[lson][id], 0); add_edge(seg[rt][id], seg[rson][id], 0);
    }else {
        add_edge(seg[lson][id], seg[rt][id], 0); add_edge(seg[rson][id], seg[rt][id], 0);
    }
}
void query(int id,int L,int R,int l,int r,int rt) {
    if(L <= l && r <= R) {
        vs.push_back(seg[rt][id]);
        return;
    }
    int mid = (l + r) >> 1;
    if(L > mid) query(id, L, R, mid+1, r, rson);
    else if(R <= mid) query(id,L,R,l,mid,lson);
    else {
        query(id,L,mid,l,mid,lson); query(id,mid+1,R,mid+1,r,rson);
    }
}
void dij() {
    for(int i = 1; i <= inde; ++i) dis[i] = INF;
    dis[st] = 0;
    A.v = st; A.w = 0;
    priority_queue<lp> Q;
    Q.push(A);
    while(!Q.empty()) {
        B = Q.top(); Q.pop();
        int u = B.v;
        if(dis[u] < B.w) continue;
        for(int i = head[u]; ~i; i = cw[i].nex) {
            int v = cw[i].v;
            if(dis[v] > dis[u] + cw[i].w) {
                dis[v] = dis[u] + cw[i].w;
                A.v = v; A.w = dis[v];
                Q.push(A);
            }
        }
    }
}
int main() {
    scanf("%d%d%d", &n, &q, &st);
    int op, l, r, w, u, v;
    memset(head, -1, sizeof(head));
    tot = -1;
    inde = n;
    build(1, 1, n, 1); build(0, 1, n, 1);
    while(q--) {
        scanf("%d", &op);
        if(op == 1) {
            scanf("%d%d%d", &u, &v, &w);
            add_edge(u, v, w);
        }else if(op == 2) {
            scanf("%d%d%d%d", &u, &l, &r, &w);
            vs.clear();
            query(1, l, r, 1, n, 1);
            for(auto x : vs) add_edge(u, x, w);
        }else if(op == 3) {
            scanf("%d%d%d%d", &u, &l, &r, &w);
            vs.clear();
            query(0, l, r, 1, n, 1);
            for(auto x : vs) add_edge(x, u, w);
        }
    }
    dij();
    for(int i = 1; i <= n; ++i) {
        if(dis[i] >= INF) dis[i] = -1;
        printf("%lld ", dis[i]);
    }
    printf("\n");
    return 0;
}



Problem Description

在这里插入图片描述

转载于:https://www.cnblogs.com/Cwolf9/p/9761711.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值