NC 22594 Dijkstra

题意

传送门 NC 22594

题解

由于最多只能从 k k k 个戒严的点出发到达任意一个点,则对于图上每个点,有经过 0 − k 0-k 0k 个戒严点共 k k k 种状态;对不同状态求最短路即可。

#include 
using namespace std;
#define inf 0x3f3f3f3f
#define maxv 805
#define maxk 15
typedef pair<int, int> P;
struct node
{
    int d, v, n;
    bool operator<(const node &a) const
    {
        return d > a.d;
    }
};
struct edge
{
    int to, cost;
};
vector<edge> G[maxv];
int n, m, k, f[maxv], d[maxv][maxk], used[maxv][maxk];

void dijkstra(int s)
{
    priority_queue<node> que;
    memset(d, 0x3f, sizeof(d));
    memset(used, 0, sizeof(used));
    d[s][0] = 0;
    que.push(node{0, s, 0});
    while (!que.empty())
    {
        node p = que.top();
        que.pop();
        int v = p.v, n = p.n;
        if (used[v][n] || n > k) continue;
        used[v][n] = 1;
        for (int i = 0; i < G[v].size(); i++)
        {
            edge &e = G[v][i];
            int d2 = e.cost + d[v][n], n2 = n + (f[v] ? 1 : 0);
            if (d2 < d[e.to][n2])
            {
                d[e.to][n2] = d2;
                que.push(node{d[e.to][n2], e.to, n2});
            }
        }
    }
}

int main()
{
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= n; i++) scanf("%d", f + i);
    for (int i = 0; i < m; i++)
    {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        G[u].push_back(edge{v, w});
        G[v].push_back(edge{u, w});
    }
    dijkstra(1);
    int res = *min_element(d[n], d[n] + k + 1);
    printf("%d\n", res == inf ? -1 : res);
    return 0;
}

你可能感兴趣的:(图论)