bzoj1598

K短路

和超级钢琴之类的差不多

先反图跑最短路,从原点向外拓展,每个点最多拓展k次,否则不可能是k短路

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int N = 1e4 + 5, inf = 0x3f3f3f3f;
int rd()
{
    int x = 0, f = 1;
    char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}
int n, m, k, cnt = 1;
int h[N], d[N], vis[N], ans[N];
struct edge { int nxt, to, w; } e[N << 1];
void link(int u, int v, int w)
{
    e[++cnt].nxt = h[u];
    h[u] = cnt;     
    e[cnt].to = v;
    e[cnt].w = w;
}
namespace I 
{
    int cnt = 1;
    int h[N];
    struct edge { int nxt, to, w; } e[N << 1];
    void link(int u, int v, int w)
    {
        e[++cnt].nxt = h[u];
        h[u] = cnt;
        e[cnt].to = v;
        e[cnt].w = w;
    }
    void dij(int s, int *d) 
    {
        priority_queue<pii, vector<pii>, greater<pii> > q;
        for(int i = 1; i <= n; ++i) d[i] = inf;
        d[s] = 0;
        q.push(make_pair(0, s));
        while(!q.empty())
        {
            pii o = q.top();
            q.pop();
            int u = o.second;
            if(d[u] < o.first) continue;
            for(int i = h[u]; i; i = e[i].nxt) if(d[e[i].to] > d[u] + e[i].w)
            {
                d[e[i].to] = d[u] + e[i].w;
                q.push(make_pair(d[e[i].to], e[i].to));
            }
        } 
    }
}
int main()
{
    n = rd();
    m = rd();
    k = rd();
    for(int i = 1; i <= m; ++i)
    {
        int u = rd(), v = rd(), w = rd();
        I :: link(v, u, w);
        link(u, v, w);
    }
    I :: dij(1, d);
    priority_queue<pii, vector<pii>, greater<pii> > q;
    q.push(make_pair(d[n], n));
    memset(ans, -1, sizeof(ans));
    while(!q.empty())
    {
        int u = q.top().second, dis = q.top().first;
        q.pop();
        ++vis[u];
        if(u == 1) 
        {
            ans[vis[u]] = dis;
            if(vis[u] == k) break;
        }
        if(vis[u] <= k) for(int i = h[u]; i; i = e[i].nxt) q.push(make_pair(dis - d[u] + d[e[i].to] + e[i].w, e[i].to));
    }
    for(int i = 1; i <= k; ++i) printf("%d\n", ans[i]);
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/19992147orz/p/8041131.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值