|BZOJ 2763|最短路|[JLOI2011]飞行路线

BZOJ 2763

分层图最短路

注意:priority_queue默认排序序列是从大到小的,所以重载小于符号时要a>b
以后权值一律写w,不要用v或c!

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define fo(i, j, k) for (i=(j);i<=(k);i++)
#define fd(i, k, j) for (i=(k);i>=(j);i--)
#define fg(i, u) for (i=0;i<G[u].size();i++)
#define fe(i, u) for (i=head[u];i!=-1;i=e[i].next)
#define rd(a) scanf("%d", &a)
#define rd2(a, b) scanf("%d%d", &a, &b)
#define rd3(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define ms(i, j) memset(i, j, sizeof i)
#define FN2 "bzoj2763" 
using namespace std;

const int MAXN = 1200100, INF = 0x3f3f3f3f;

struct edge{int v, c;}e[MAXN<<2];
struct data {
    int u, c;
    bool operator < (data const &b) const {
        return c>b.c;
    }
};
int n, m, k, en, dis[MAXN], s, t, vi[MAXN];
vector<int> G[MAXN];

void ins(int u, int v, int c) {
    en++, e[en].v = v, e[en].c = c, G[u].push_back(en);
}
void pre() {
    int i; en = 0;
    fo (i, 0, n*(k+2)) G[i].clear(), dis[i] = INF, vi[i] = false;
}
void init() {
    int i,j;
    pre();
    rd2(s, t);
    fo (i, 1, m) {
        int a, b, c;
        rd3(a, b, c);
        fo (j, 0, k) {
            ins(a+j*n, b+j*n, c), ins(b+j*n, a+j*n, c);
            if (j!=k) ins(a+j*n, b+(j+1)*n, 0), ins(b+j*n, a+(j+1)*n, 0);
        }
    }
}
void solve() {
    int i, ans = INF;
    priority_queue<data> q;
    dis[s] = 0, q.push((data){s, dis[s]});
    while (!q.empty()) {
        data p = q.top(); q.pop();
        int u = p.u;
        if (vi[u]) continue;
        vi[u] = true;
        for (i=0;i<G[u].size();i++) {
            int v = e[G[u][i]].v;
            if (dis[v]>dis[u]+e[G[u][i]].c) {
                dis[v] = dis[u]+e[G[u][i]].c;//用dis[u],因为有重边 
                q.push((data){v, dis[v]});
            }
        }
    }
    fo (i, 0, k) {
        ans = min(ans, dis[t+i*n]);
    }
    printf("%d\n", ans);
}
int main() {
    #ifndef ONLINE_JUDGE
    freopen(FN2".in","r",stdin);freopen("1.out","w",stdout);
    #endif
    while (rd3(n,m,k)==3) init(), solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值