其他分享
首页 > 其他分享> > 最短路简单题——[USACO09FEB]Revamping Trails G

最短路简单题——[USACO09FEB]Revamping Trails G

作者:互联网

题目大意:给定n个点,m条边的无向图,可以让任意k条边的边权变为0,求从1号点到n号点的最短路。

思路:分层图板题,思路如下:

我们把这个图复制成k+1层图,每一层都与原来的无向图相同,但是任两层图之间的边权为0。思考到一个性质,即因为两层图之间建的是单向图,所以最多只会走k条边权为0的边,走到第i层即说明已经使用了i-1次将边权变为0的机会,所以我们通过分层图的思想把这样一个题变成了最短路板题。下面是代码:

#include <bits/stdc++.h>

using namespace std;

typedef pair <int, int> P;

priority_queue <P, vector <P>, greater <P> > Q;

struct node {
    int to, nxt, len;
}e[5000005]; int head[2500005], dis[2500005], vis[2500005], tot;
inline void add_e(int u, int v, int w) {e[++tot].to = v; e[tot].nxt = head[u]; head[u] = tot; e[tot].len = w;}

void dijkstra(int s)
{
    memset(dis, 0x3f, sizeof dis);
    dis[s] = 0;
    Q.push(make_pair(0, s));
    while (!Q.empty())
    {
        int u = Q.top().second; Q.pop();
        if (vis[u]) continue;
        else vis[u] = 1;
        for (int i = head[u]; i; i = e[i].nxt)
        {
            int v = e[i].to;
            if (dis[v] > dis[u] + e[i].len)
            {
                dis[v] = dis[u] + e[i].len;
                Q.push(make_pair(dis[v], v));
            }
        }
    }
}

int main()
{
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1, x, y, z; i <= m; i++)
    {
        scanf("%d%d%d", &x, &y, &z);
        add_e(x, y, z);
        add_e(y, x, z);
        for (int j = 1; j <= k; j++)
        {
            add_e(x + j * n, y + j * n, z);
            add_e(y + j * n, x + j * n, z);
            add_e(x + (j - 1) * n, y + j * n, 0);
            add_e(y + (j - 1) * n, x + j * n, 0);
        }
    }
    dijkstra(1); int ans = dis[n];
    for (int i = 1; i <= k; i++)
    {
        ans = min(ans, dis[i * n + n]);
    } printf("%d", ans);
}

 

标签:head,int,Trails,Revamping,tot,USACO09FEB,vis,len,dis
来源: https://www.cnblogs.com/Chasing-Dreams-Z/p/14615139.html