• 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
    ",d[(k+1)*n]);
    	return 0;
    }
    
  • 相关阅读:
    09安装运行redis-trib.rb所需的环境
    08Redis入门指南笔记(集群)
    win10 64位安装memcache扩展和开启redis扩展
    ubuntu 安装 lamp 和配置虚拟机
    Ubuntu 安装phpmyadmin 和配置
    ubuntu的 mysql 存储目录迁移
    ubuntu16.04安装php5
    PHP文件操作功能函数大全
    PHP 通用检测函数集
    PHP文件操作的经典案例
  • 原文地址:https://www.cnblogs.com/DarkValkyrie/p/11580201.html
Copyright © 2020-2023  润新知