您的位置:首页 > 其它

分层图

2017-03-17 08:29 176 查看

分层图 及堆优化dijkstra

遇到了据说个不太常用的思想叫分层图

顺便补补课,写个堆优化的dijkstra

分层图主要是应用于 变化的最短路问题 问题常表现为一个最短路问题上加一些手脚,如减小一些边权,改变一些连接,但事先又不知道,或可以自由选择改变哪个边,最终求最短路等等。由于无法知道改变了那些边,所以用到分层图思想。

可以理解为 平行宇宙 一样的东西 就是把原图复制出来k个,然后在原图连接的基础上,在相邻层中间加一些要求的变化边,通常是单向的(保证从每一层到下一层不再回来),再跑最短路。

发个题吧

Illegal Motor (Motor.c/cpp/pas)

Description

在你的强力援助下,PCY 成功完成了之前的所有任务,他觉得,现在正是出去浪的大好时光。

于是,他来到高速公路上,找到一辆摩的前往几千公里以外他心仪的那家黄焖鸡米饭。

由于 PCY 的品味异于常人,途经几百个城市的黄焖鸡米饭他都不屑一顾,他只愿意前往他心中最

好的那家,但是为了一碗二十块钱的黄焖鸡米饭,他不愿意花上几千块的路费,他希望路费尽量

少。高速路上的警察叔叔被他的行为所打动,于是在多方协调下,最多 K 条城市之间的高速收费站

愿意免费为 PCY 放行(可以任意选择)。

显然,PCY 已经筋疲力尽,不想再动用自己的数学天才来计算他可以花费的最小路费,因此他希

望你可以帮他最后一次,他说他可以请你吃大碗的黄焖鸡米饭,还可以加一瓶豆奶。

现在给你 N 个城市(编号为 0 … N - 1),M 条道路,和每条高速公路的花费 Wi,以及题目所描

述的 K。 PCY 想从城市 S 到城市 T,因为他对 T 城市的黄焖鸡米饭情有独钟。

Input (Prefix.in)

第一行,三个整数 N,M,K,如题意所描述

第二行,两个整数 S,T,代表出发城市和目标城市编号

接下来 M 行,每行三个整数 X,Y,W,代表 X 和 Y 城市之间的高速公路收费为 W 元

Output (Prefix.out)

共一行,输出一个整数,代表 PCY 最少需要花费的路费。NOIP 模拟题

7

Sample Input

Sample Output

Explanation

自己动手,丰衣足食

Hint

对于 10%的数据,N <= 100,K = 0

对于 30%的数据,N <= 5,M <= 10,K <= 2

对于 100%的数据,N <= 10000,M <= 50000,K <= 10,Wi <= 10000

内存限制 256M,时间限制 1s

我们建个原图,再复制k层出来然后这样:

原图x到y有一条边权为13的边,然后再每两个相邻的层之间 从x到y’连个边权为0的边,y到x’亦如此,这样以后跑图时可以从x到y跑这个变,即不花钱,又因为它是单向的,所以跑不回去了,保证了不会死循环或出意外。最终比较每层图的dis【t】值,取最小的,即是通过了有些免费路的最小值。

因为任意选择免费路,所以不知道那条免费最好,所以分层来跑,即最后的最短路就是包含了一些边权为零的路,但不一定跑了那种组合,所以每层t点都应比较一下。

发个图(纯自己手画,有点丑)



像这样从x到y就可以走一条边权为0的边,然后再下一层中继续跑最短路,也有可能没走这个而走了另一条路,则两层的t就不一定哪个更近,所以比下。

分层图说完了,再来浅谈一下堆优化dijkstra。

优化的地方主要是在取出剩余点中dis最小的点时用了堆,直接取,而非循环一边。堆里存两个东西:一维是dis,并按这个维护的小根堆,然后二维是点的序号,取出来更新时也要用到。

好了,代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#define inf 0x7f7f7f7f
#define N 200050
#define M 4000010
using namespace std;

int n,m,k,s,t;
int  dis
,ans,maxn,sum,nown;

struct E{
int to,next,wi;
}a[M];int last
,cnt;

void bud(int u,int v,int w)
{
a[++cnt].to=v;a[cnt].wi=w;
a[cnt].next=last[u];last[u]=cnt;
}

typedef pair<int,int>hp;//自定义类型,一维是dis值,二维是序号

void dijkstra()//堆优化dijkstra
{
priority_queue<hp,vector<hp>,greater<hp> >heap;
memset(dis,inf,sizeof(dis));
dis[s]=0;
heap.push(hp(0,s));
while(!heap.empty()){
hp now=heap.top();heap.pop();
int x=now.second;
if(dis[x]<now.first)continue;
for(int i=last[x];i;i=a[i].next){
if(dis[a[i].to]>dis[x]+a[i].wi){
dis[a[i].to]=dis[x]+a[i].wi;
heap.push(hp(dis[a[i].to],a[i].to));
}
}
}
}

int main()
{
freopen("Motor.in","r",stdin);
freopen("Motor.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
scanf("%d%d",&s,&t);
for(int i=1;i<=m;++i){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
for(int j=0;j<=k;++j){//分层建图
bud(u+n*j,v+n*j,w);
bud(v+n*j,u+n*j,w);
if(j<k){
bud(u+n*j,v+n*(j+1),0);
bud(v+n*j,u+n*(j+1),0);
}
}
}
ans=inf;
dijkstra();
for(int i=0;i<=k;++i)ans=min(ans,dis[t+i*n]);//比较最优
printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dijkstra 优化 分层图