P2939 [USACO09FEB]改造路[分层图最短路]

Posted darkvalkyrie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2939 [USACO09FEB]改造路[分层图最短路]相关的知识,希望对你有一定的参考价值。

题意翻译

约翰一共有N)个牧场.由M条布满尘埃的小径连接.小径可 以双向通行.每天早上约翰从牧场1出发到牧场N去给奶牛检查身体.

通过每条小径都需要消耗一定的时间.约翰打算升级其中K条小径,使之成为高 速公路.在高速公路上的通行几乎是瞬间完成的,所以高速公路的通行时间为0.

请帮助约翰决定对哪些小径进行升级,使他每天从1号牧场到第N号牧场所花的时间最短

解析

提高练习场看到这题,瞄一眼,诶,这不是分层图裸题吗???


【啥是分层图】

分层图,简单来说,就是把一张图复制多次,分为多份,每层图代表一种异于其它层次的图的状态。在这些互相平行本无干扰的图中,我们加入一些关键边,相当于该图某种特定状态到另一种状态的转移。类似动态规划,在转移后,我们就无法回到之前的状态了。

【这题咋做】

把图分为k层,对于题述每条边,我们不仅要在每层图上连一次权值为\(d\)的边,构造分层图,还要在每层图之间连一次权值为\(0\)的边,以添加转移边。

如果最短路经过了一条权值为\(0\)的边,就相当于把一条路升级了,要升k次,我们就建k层图。显然,由于我们取的是最短路,不会存在重复升级的情况(想一想,为什么)。

参考代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 3000010
#define MOD 2520
#define E 1e-12
#define ll long long
using namespace std;
inline int read()

    int f=1,x=0;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;

struct rec
    int next,ver,edge;
g[N<<1];
int head[N],tot,n,m,k;
ll d[N];
bool v[N];
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q;
inline void add(int x,int y,int val)

    g[++tot].ver=y,g[tot].edge=val;
    g[tot].next=head[x],head[x]=tot;

inline void dijkstra(int s)

    memset(v,0,sizeof(v));
    memset(d,0x3f,sizeof(d));
    d[s]=0;q.push(make_pair(0,s));
    while(q.size())
        int x=q.top().second;q.pop();
        if(v[x]) continue;
        v[x]=1;
        for(int i=head[x];i;i=g[i].next)
            int y=g[i].ver,z=g[i].edge;
            if(d[y]>d[x]+z)
                d[y]=d[x]+z;
                q.push(make_pair(d[y],y));
            
        
    

int main()

    n=read(),m=read(),k=read();
    for(int i=1;i<=m;++i)
        int u=read(),v=read(),val=read();
        for(int j=0;j<=k;++j)
            add(u+j*n,v+j*n,val),add(v+j*n,u+j*n,val);
            add(u+j*n,v+j*n+n,0),add(v+j*n,u+j*n+n,0);
        
    
    dijkstra(1);
    printf("%lld\n",d[(k+1)*n]);
    return 0;

以上是关于P2939 [USACO09FEB]改造路[分层图最短路]的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P2939 [USACO09FEB]改造路Revamping Trails

luogu P2939 [USACO09FEB]改造路Revamping Trails 题解

USACO09FEB 改造路Revamping Trails(分层图模板)

分层图最短路,dijstraP2939 [USACO09FEB]改造路Revamping Trails

USACO09FEB改造路Revamping Trails

luoguP2939 [USACO09FEB]改造路Revamping Trails