bzoj 2763: [JLOI2011]飞行路线 分层图

题目链接

n个点m条路, 每条路有权值,  给出起点和终点, 求一条路使得权值最小。可以使路过的路中, k条路的权值忽略。

其实就是多一维, 具体看代码

#include<bits/stdc++.h>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, a, n) for(int i = a; i<n; i++)
#define ull unsigned long long
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int mod = 1e9+7;
const int inf = 1061109567;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
const int maxn = 5e4+5;
int dis[12][60005], in[12][60005], num, head[maxn*2];
int n, m, k, s, t;
struct edge
{
    int to, nextt, w;
}e[maxn*2];
struct node
{
    int u, x;
    node(){}
    node(int u, int x):u(u),x(x){}
};
void init() {
    mem1(head);
    num = 0;
}
void add(int u, int v, int w) {
    e[num].to = v;
    e[num].nextt = head[u];
    e[num].w = w;
    head[u] = num++;
}
queue <node> q;
int dij() {
    mem2(dis);
    q.push(node(s, 0));
    dis[0][s] = 0;
    in[0][s] = 1;
    while(!q.empty()) {
        node tmp = q.front(); q.pop();
        int u = tmp.u, x = tmp.x;
        in[x][u] = 0;
        for(int i = head[u]; ~i; i = e[i].nextt) {
            int v = e[i].to;
            if(dis[x][v]>dis[x][u]+e[i].w) {
                dis[x][v] = dis[x][u]+e[i].w;
                if(!in[x][v]) {
                    in[x][v] = 1;
                    q.push(node(v, x));
                }
            }
        }
        if(x<k) {
            x++;
            for(int i = head[u]; ~i; i = e[i].nextt) {
                int v = e[i].to;
                if(dis[x][v]>dis[x-1][u]) {
                    dis[x][v] = dis[x-1][u];
                    if(!in[x][v]) {
                        in[x][v] = 1;
                        q.push(node(v, x));
                    }
                }
            }
        }
    }
    int ans = inf;
    for(int i = 0; i<=k; i++)
        ans = min(ans, dis[i][t]);
    return ans;
}
int main()
{
    int x, y, z;
    cin>>n>>m>>k>>s>>t;
    init();
    while(m--) {
        scanf("%d%d%d", &x, &y, &z);
        add(x, y, z);
        add(y, x, z);
    }
    int ans = dij();
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/yohaha/p/5068070.html