分层图 (可以选择K条路的权为0,求最短路)
分层图可以处理从图中选取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,求最短路)的更多相关文章
- poj2455 k条路最小化最长边
Secret Milking Machine Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12414 Accepted ...
- 2018icpc南京网络赛-L Magical Girl Haze (分层图最短路)
题意: 有向图,可以把k条路的长度变为0,求1到n的最短路 思路: 将图复制k份,一共k+1层图,对于每一条i→j,都连一条低层的i→高层的j,并且权值为0 即对每一对<i,j,w>,都加 ...
- bzoj 2763: [JLOI2011]飞行路线 分层图
题目链接 n个点m条路, 每条路有权值, 给出起点和终点, 求一条路使得权值最小.可以使路过的路中, k条路的权值忽略. 其实就是多一维, 具体看代码 #include<bits/stdc++ ...
- 2019牛客多校第四场J free——分层图&&最短路
题意 一张无向图,每条边有权值,可以选择不超过 $k$ 条路使其权值变成0,求 $S$ 到 $T$ 的最短路.(同洛谷 P4568) 分析 首先,分层图最短路可以有效解决这种带有 「阶段性」的最短路, ...
- Codeforces Gym Joyride(分层图,dijkstra)
题意:有一张图,每条边有一个边权t表示经过所花时间,每个点有两个权t.p,分别表示经过该点所花时间和所花费用,要求找一条路径,从点1出发再回到点1,所花时间恰好为x且费用最小,输出其费用,找不到则输出 ...
- ACM-ICPC 2018 南京赛区网络预赛 L 【分层图最短路】
<题目链接> 题目大意: 有N个城市,这些城市之间有M条有向边,每条边有权值,能够选择K条边 边权置为0,求1到N的最短距离. 解题分析: 分层图最短路模板题,将该图看成 K+1 层图,然 ...
- bzoj2763: [JLOI2011]飞行路线(分层图spfa)
2763: [JLOI2011]飞行路线 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3234 Solved: 1235[Submit][Stat ...
- poj 3613 经过k条边最短路 floyd+矩阵快速幂
http://poj.org/problem?id=3613 s->t上经过k条边的最短路 先把1000范围的点离散化到200中,然后使用最短路可以使用floyd,由于求的是经过k条路的最短路, ...
- 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, ...
随机推荐
- ACM学习历程—HDU 5534 Partial Tree(动态规划)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5534 题目大意是给了n个结点,让后让构成一个树,假设每个节点的度为r1, r2, ...rn,求f(x ...
- S3C2410中文芯片手册-11.串口
目录 11 UART Overview Featrues UART Operation Data Transmission Data Reception Auto Flow Control(AFC) ...
- JS数组的sort排序
数组sort方法排序var aa=[6,2,1,5]//默认是从小到大排序aa.sort()[1, 2, 5, 6] //下面也是从小到大排序aa.sort(function(a,b){return ...
- html之ajax
正常情况下,html中的ajax(也就是XMLHttpRequest对象)是不能跨域的.(特殊情况,此处不讨论,请网上Google) ---跨域:是url的协议或ip或端口,其中有一个不同,就是跨域. ...
- BZOJ3039:玉蟾宫
浅谈栈:https://www.cnblogs.com/AKMer/p/10278222.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php?id ...
- 【Android学习笔记】 点击穿透(Click Through)
问题:开发一个App,主界面用了Activity,子页面用了Fragment.从Activity跳转到Fragment后Fragment透明,并且点击击穿到Axtivity. 分析:刚开始没有注意到点 ...
- 用Raspberry Pi搭建Azure IOT解决方案
Raspberry Pi是一款基于Linux的单板机电脑.它由英国的树莓派基金会所开发,目的是以低价硬件及自由软件刺激在学校的基本计算机科学教育.树莓派配备一枚博通(Broadcom)出产的ARM架构 ...
- UML核心元素--边界
定义:边界是无形的,是可大可小的,同时参与者.用例和边界又有着相生相克的性质.与其说边界是UML元素,还不如说它是一种分析方法. 1.需求是动态的过程:系统边界是无形的,看不到的,不好理解,倒不如说需 ...
- js提交数据时需判断是点击事件还是回车键
使用回车键实质还是点击事件==回车时将焦点聚居在某个标签上. Html代码: <div id="btlogin" class="btlogin">& ...
- <正则吃饺子> :关于使用pd创建表时需要注意的地方
公司项目使用pd设计数据库表.之前用过,但是年代比较久远了,有些细节忘记了,今天重新使用时候,生疏了,现在稍微记录下吧. 1.pd创建表的使用,可以直接从网上搜索,博文比较多,如 “pd 设计数据库表 ...