码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-09-24 19:32:52      阅读:106      评论:0      收藏:0      [点我收藏+]

标签:||   多次   stream   提高   set   转移   哪些   这不   make   

题意翻译

约翰一共有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]改造路[分层图最短路]

标签:||   多次   stream   提高   set   转移   哪些   这不   make   

原文地址:https://www.cnblogs.com/DarkValkyrie/p/11580201.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!