分层图可以处理从图中选取k条边使其边权变为0,求最短路

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 最少需要花费的路费。

借鉴Kigo的想法,分层图就是K层平行宇宙,每一层里有一个完整的图,但平行宇宙之间有互相连通的虫洞,可以从一个平行宇宙中的一个点瞬间到达下一个平行宇宙(原先x->y 边权为w,现在x->y’边权为0),然而虫洞是单向的,你不能回到上一个平行宇宙,只能向下一个平行宇宙走;最终,每一个平行宇宙都有同样的目的地,看到哪一个目的地最省钱

在这里,K层分层图说明最多有K条0边权的路可以走,建图后跑最短路即可

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXM 5000000
using namespace std; int s,t,n,m,k; inline int Read(){
int x=;char ch=getchar();
while(ch<'' || ch>''){ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x;
} struct E{
int next,to,v;
}edge[MAXM];
int head[MAXM];int edge_num;
int dis[MAXM]; void addedge(int x,int y,int z){
edge[++edge_num].next=head[x];
edge[edge_num].to=y;
edge[edge_num].v=z;
head[x]=edge_num;
} int que[MAXM];int front,tail;
bool inque[MAXM]; void PUSH(int x){
tail++;
if(tail==) tail=;
que[tail]=x;inque[x]=;
} int POP(){
front++;
if(front==) front=;
int t=que[front];
inque[t]=;
return t;
} void SPFA(int x){
memset(dis,0x7f,sizeof(dis));
PUSH(x);
dis[x]=;
while(front<tail){
int fro=POP();
int i;
for(i=head[fro];i;i=edge[i].next){
if(dis[edge[i].to]>dis[fro]+edge[i].v){
dis[edge[i].to]=dis[fro]+edge[i].v;
if(!inque[edge[i].to]){
PUSH(edge[i].to);
}
}
}
}
} void solve(){
SPFA(s);
int i;
int ans=0x7fffffff;
for(i=;i<=k;i++){
ans=min(ans,dis[t+n*i]);
}
printf("%d\n",ans);
} int main(){
freopen("Motor.in","r",stdin);
freopen("Motor.out","w",stdout);
n=Read();m=Read();k=Read();s=Read();t=Read();
int i;
if(k==){
for(i=;i<=m;i++){
int a=Read();int b=Read();int c=Read();
int j;
addedge(a,b,c);
addedge(b,a,c);
}
SPFA(s);
printf("%d\n",dis[t]);
return ;
}
for(i=;i<=m;i++){
int a=Read();int b=Read();int c=Read();
int j;
for(j=;j<=k;j++){
addedge(a+n*j,b+n*j,c);
addedge(b+n*j,a+n*j,c);
if(j<k){
addedge(a+n*j,b+n*(j+),);
addedge(b+n*j,a+n*(j+),);
}
}
}
solve();
return ;
}

不推荐

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = ;
const int maxm = ;
const int inf = 0x3f3f3f3f; void Read(int& x)
{
char t = getchar();
while (t < '' || t > '') t = getchar();
x = ;
while (t >= '' && t <= '') {
x = x * + t - '';
t = getchar();
}
} struct Heap
{
int place[maxn], val[maxn], idx[maxn], node_cn; Heap() { node_cn = ; memset(place, , sizeof(place)); } inline void Swap(int x, int y)
{
swap(place[idx[x]], place[idx[y]]);
swap(val[x], val[y]);
swap(idx[x], idx[y]);
} void adjustup(int x)
{
while (x > ) {
if (val[x] < val[x >> ]) {
Swap(x, x >> );
x >>= ;
} else {
break;
}
}
} void adjustdown(int x)
{
int v;
while ((x << ) <= node_cn) {
v = x << ;
if (v + <= node_cn && val[v + ] < val[v]) v = v + ;
if (val[x] > val[v]) {
Swap(x, v);
x = v;
} else {
break;
}
}
} void insert(int id, int v)
{
if (place[id]) {
val[place[id]] = -inf;
adjustup(place[id]);
val[] = v;
adjustdown();
} else {
node_cn ++;
val[node_cn] = v, idx[node_cn] = id, place[id] = node_cn;
adjustup(node_cn);
} } void pop()
{
Swap(, node_cn);
node_cn --;
adjustdown();
}
}; int fst[maxn], edge_cn = ;
int u[maxm], v[maxm], w[maxm], nxt[maxm]; void addedge(int x, int y, int _w)
{
edge_cn ++;
u[edge_cn] = x, v[edge_cn] = y, w[edge_cn] = _w;
nxt[edge_cn] = fst[x];
fst[x] = edge_cn;
} int n, m, k, s, t;
int dis[maxn]; void input()
{
int x, y, z;
memset(fst, -, sizeof(fst));
Read(n), Read(m), Read(k);
Read(s), Read(t);
for (register int i = ; i <= m; i++) {
Read(x), Read(y), Read(z);
for (register int j = ; j <= k; j++) {
addedge(x + n * j, y + n * j, z);
addedge(y + n * j, x + n * j, z);
if (j < k) {
addedge(x + n * j, y + n * (j + ), );
addedge(y + n * j, x + n * (j + ), );
}
}
}
} Heap heap;
bool vis[maxn]; void Dijsktra()
{
int cn;
memset(dis, inf, sizeof(dis));
dis[s] = ;
heap.insert(s, );
while (heap.node_cn) {
cn = heap.idx[];
heap.pop();
if (vis[cn]) continue;
vis[cn] = true;
for (register int i = fst[cn]; i != -; i = nxt[i]) {
if (!vis[v[i]] && dis[v[i]] > dis[cn] + w[i]) {
dis[v[i]] = dis[cn] + w[i];
heap.insert(v[i], dis[v[i]]);
}
}
}
} void solve()
{
int ans = inf;
Dijsktra();
for (register int i = ; i <= k; i++) ans = min(ans, dis[t + i * n]);
printf("%d\n", ans);
} int main()
{
#ifndef ONLINE_JUDGE
freopen("Motor.in", "r", stdin);
freopen("Motor.out", "w", stdout);
#endif input();
solve(); #ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return ;
}

推荐:堆优化 , DJ



分层图 (可以选择K条路的权为0,求最短路)的更多相关文章

  1. poj2455 k条路最小化最长边

    Secret Milking Machine Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12414   Accepted ...

  2. 2018icpc南京网络赛-L Magical Girl Haze (分层图最短路)

    题意: 有向图,可以把k条路的长度变为0,求1到n的最短路 思路: 将图复制k份,一共k+1层图,对于每一条i→j,都连一条低层的i→高层的j,并且权值为0 即对每一对<i,j,w>,都加 ...

  3. bzoj 2763: [JLOI2011]飞行路线 分层图

    题目链接 n个点m条路, 每条路有权值,  给出起点和终点, 求一条路使得权值最小.可以使路过的路中, k条路的权值忽略. 其实就是多一维, 具体看代码 #include<bits/stdc++ ...

  4. 2019牛客多校第四场J free——分层图&&最短路

    题意 一张无向图,每条边有权值,可以选择不超过 $k$ 条路使其权值变成0,求 $S$ 到 $T$ 的最短路.(同洛谷 P4568) 分析 首先,分层图最短路可以有效解决这种带有 「阶段性」的最短路, ...

  5. Codeforces Gym Joyride(分层图,dijkstra)

    题意:有一张图,每条边有一个边权t表示经过所花时间,每个点有两个权t.p,分别表示经过该点所花时间和所花费用,要求找一条路径,从点1出发再回到点1,所花时间恰好为x且费用最小,输出其费用,找不到则输出 ...

  6. ACM-ICPC 2018 南京赛区网络预赛 L 【分层图最短路】

    <题目链接> 题目大意: 有N个城市,这些城市之间有M条有向边,每条边有权值,能够选择K条边 边权置为0,求1到N的最短距离. 解题分析: 分层图最短路模板题,将该图看成 K+1 层图,然 ...

  7. bzoj2763: [JLOI2011]飞行路线(分层图spfa)

    2763: [JLOI2011]飞行路线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3234  Solved: 1235[Submit][Stat ...

  8. poj 3613 经过k条边最短路 floyd+矩阵快速幂

    http://poj.org/problem?id=3613 s->t上经过k条边的最短路 先把1000范围的点离散化到200中,然后使用最短路可以使用floyd,由于求的是经过k条路的最短路, ...

  9. ACM-ICPC 2018 南京赛区网络预赛 L. Magical Girl Haze 最短路+分层图

    类似题解 There are NN cities in the country, and MM directional roads from uu to v(1\le u, v\le n)v(1≤u, ...

随机推荐

  1. D唐纳德和他的数学老师(华师网络赛)(二分匹配,最大流)

    Time limit per test: 1.0 seconds Memory limit: 256 megabytes 唐纳德是一个数学天才.有一天,他的数学老师决定为难一下他.他跟唐纳德说:「现在 ...

  2. jquery.cxSelect插件,城市没单位

    jquery.cxSelect插件,新增城市没单位也能显示出来的功能. 具体,请查看修改后的插件代码:(主要是FixNoUnit函数) /*! * jQuery cxSelect * @name jq ...

  3. Excel用vlookup方法匹配数据

    (1) VLOOKUP是一个查找函数,给定一个查找的目标,它就能从指定的查找区域中查找返回想要查找到的值.它的基本语法为:     VLOOKUP(查找目标,查找范围,返回值的列数,精确OR模糊查找) ...

  4. nginx实现带参数目录域名重定向二级域名方法

    本文章介绍了关于nginx实现带参数目录域名重定向二级域名方法,有需要学习的朋友可参考一下. 下面的代码是基于nginx的子目录301到其他域名(URL)的规则.作用是例如访问http://www.p ...

  5. css基础知识一

    1.CSS (Cascding Style Sheet)层叠样式表 级联样式表 样式表 2.CSS作用: 修改页面中元素的显示样式 能够实现内容与表现的分离 提高代码的可重用性和可维护性 3.导入CS ...

  6. Go语言是如何处理栈的

    转自:http://tonybai.com/2014/11/05/how-stacks-are-handled-in-go/ Go 1.4Beta1刚刚发布,在Go 1.4Beta1中,Go语言的st ...

  7. Ruby模块(module)

    Ruby模块(module) 2013-04-03 16:47:09|  分类: Ruby |  标签:ruby  require  load  extend  include  |字号 订阅     ...

  8. 我推荐的一些C\C++书籍

    原文链接: 我推荐的一些C\C++书籍 人们常常问我有什么C++和编程的书籍推荐,也许是因为我在PowerDNS有一个关于"编写可读性良好的C++代码"的演讲.这篇博文可以作为我对 ...

  9. C++之Stack模板类

    假设有这样一种情况:某人将一车文件交给小王.倘若小王的抽屉是空的,那么小王从车上取出最上面的文件将其放入抽屉:倘若抽屉是满的,小王从抽屉中取出最上面的文件,放入垃圾篓:倘若抽屉即不空也未满,那么小王抛 ...

  10. css 雪碧图

    CSS Sprites在国内很多人叫css精灵,是一种网页图片应用处理方式.它允许你将一个页面涉及到的所有零星图片都包含到一张大图中去,这样一来,当访问 该页面时,载入的图片就不会像以前那样一幅一幅地 ...