2019牛客多校第四场J free——分层图&&最短路
题意
一张无向图,每条边有权值,可以选择不超过 $k$ 条路使其权值变成0,求 $S$ 到 $T$ 的最短路。(同洛谷 P4568)
分析
首先,分层图最短路可以有效解决这种带有 「阶段性」的最短路,这是分层图最短路的模板题。
建立 $0~k $ 层相同的图,每层之间相邻的节点之间也用权值为0的边相连(具体操作见代码)。第 $k$ 层表示已经将 $k$ 条道路置为0。最终把每层的终点连向一个超级汇点。最短路就是从第 $0$ 层源点到超级汇点的最短路。
#include<bits/stdc++.h>
using namespace std; const int maxn = 1e6 + ;
const int maxe = 1e7 + ; //仔细算算
const int INF = 0X3f3f3f3f; struct Edge
{
int to, w, next;
}edges[maxe];
int head[maxn], cnt;
int n, m, S, T, K; void init()
{
memset(head, -, sizeof(head));
cnt = ;
} inline void AddEdge(int a, int b, int w)
{
int id = ++cnt;
edges[id].to = b;
edges[id].w = w;
edges[id].next = head[a];
head[a] = id;
} struct Node
{
int u, d; //节点的编号与距离
bool operator < (const Node x) const
{
return d > x.d;
}
};
int vis[maxn], dis[maxn]; void Dijsktra(int s)
{
priority_queue<Node>q;
memset(vis, , sizeof(vis));
memset(dis, INF, sizeof(dis));
dis[s] = ;
q.push(Node{s, dis[s]});
while(!q.empty())
{
Node x = q.top();q.pop();
int u = x.u;
if(vis[u]) continue;
vis[u] = true;
for(int i = head[u]; i != -;i = edges[i].next)
{
int v = edges[i].to;
int w = edges[i].w;
if(!vis[v] && dis[u] + w < dis[v])
{
dis[v] = dis[u] + w;
q.push(Node{v, dis[v]});
}
}
}
} int main()
{
init();
scanf("%d%d%d%d%d", &n, &m, &S, &T, &K);
for(int i = ;i < m;i++)
{
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
AddEdge(a, b, w);
AddEdge(b, a, w);
for(int j = ;j <= K;j++)
{
AddEdge(a+(j-)*n, b+j*n, );
AddEdge(b+(j-)*n, a+j*n, );
AddEdge(a+j*n, b+j*n, w);
AddEdge(b+j*n, a+j*n, w);
}
}
for(int i = ;i < K;i++) AddEdge(T+i*n, T+(i+)*n, ); //将每层终点连接到超级汇点
Dijsktra(S);
printf("%d\n", dis[T+K*n]); return ;
}
这题可以用分层图的思想来理解,但是可以用dp来写,只需对Dijsktra作一点修改,对 $dis$ 数组增加一维,$dis[i][j]$ 表示到第 $i$ 个点,用了 $j$ 次免费机会的最短路径长度。
分层图的方法比较直观,但是占用的内存较多。
#include<bits/stdc++.h>
using namespace std; const int maxn = 1e3 + ;
const int maxe = 2e3 + ; //仔细算算
const int maxk = 1e3 + ;
const int INF = 0X3f3f3f3f; struct Edge
{
int to, w, next;
}edges[maxe];
int head[maxn], cnt;
int n, m, S, T, K; void init()
{
memset(head, -, sizeof(head));
cnt = ;
} inline void AddEdge(int a, int b, int w)
{
int id = ++cnt;
edges[id].to = b;
edges[id].w = w;
edges[id].next = head[a];
head[a] = id;
} struct Node
{
int u, d, times; //节点的编号、距离和已经走0通道的次数
bool operator < (const Node x) const
{
return d > x.d;
}
};
int vis[maxn][maxk], dis[maxn][maxk]; void Dijsktra(int s)
{
priority_queue<Node>q;
memset(vis, , sizeof(vis));
memset(dis, INF, sizeof(dis));
dis[s][] = ;
q.push(Node{s, dis[s][], });
while(!q.empty())
{
Node x = q.top();q.pop();
int u = x.u, times = x.times;
if(vis[u][times]) continue;
vis[u][times] = true;
for(int i = head[u]; i != -;i = edges[i].next)
{
int v = edges[i].to, w = edges[i].w;
if(times < K && dis[u][times] < dis[v][times+]) //走0通道
{
dis[v][times+] = dis[u][times];
q.push(Node{v, dis[v][times+], times+});
}
if(dis[u][times] + w < dis[v][times]) //不走0通道
{
dis[v][times] = dis[u][times] + w;
q.push(Node{v, dis[v][times], times});
}
}
}
} int main()
{
init();
scanf("%d%d%d%d%d", &n, &m, &S, &T, &K);
for(int i = ;i < m;i++)
{
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
AddEdge(a, b, w);
AddEdge(b, a, w);
}
Dijsktra(S);
int ans = INF;
for(int i = ;i <= K;i++) ans = min(ans, dis[T][i]);
printf("%d\n", ans); return ;
}
参考链接:
1. https://blog.csdn.net/SSL_ZYC/article/details/94959850
2. https://www.luogu.org/problemnew/solution/P4568?page=2
2019牛客多校第四场J free——分层图&&最短路的更多相关文章
- 2019牛客多校第四场J free 最短路
free 题意 给出一个带权联通无向图,你需要从s走到t,你可以选择k条变让他们的权值为0问从s到t的最小权值是多少? 分析 思考一下,如果不带k条白嫖这个条件,那么这就是一个简单的dji就搞定了,我 ...
- 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数
目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...
- 2019牛客多校第四场 A meeting
链接:https://ac.nowcoder.com/acm/contest/884/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他语言10485 ...
- 2019牛客多校第四场B xor——线段树&&线性基的交
题意 给你 $n$ 个集合,每个集合中包含一些整数.我们说一个集合表示一个整数当且仅当存在一个子集其异或和等于这个整数.现在你需要回答 $m$ 次询问 ($l, r, x$),是否 $l$ 到 $r$ ...
- 2019牛客多校第四场A meeting——树的直径
题意: 一颗 $n$ 个节点的树上标有 $k$ 个点,找一点使得到 $k$ 个关键结点的最大距离最小. 分析: 问题等价于求树的直径,最小距离即为直径除2向上取整. 有两种求法,一是动态规划,对于每个 ...
- [2019牛客多校第四场][G. Tree]
题目链接:https://ac.nowcoder.com/acm/contest/884/G 题目大意:给定一个树\(A\),再给出\(t\)次询问,问\(A\)中有多少连通子图与树\(B_i\)同构 ...
- 2019牛客多校第四场D-triples I 贪心
D-triples 题意 给你一个\(n\),问至少有几个数或运算起来可以等于\(n\),并且输出数量和这个几个数.题目说明给的\(n\)一定符合条件(不会输出\(n= 1\) 之类不存在情况). 思 ...
- 2019牛客多校第四场C-sequence(单调栈+线段树)
sequence 题目传送门 解题思路 用单调栈求出每个a[i]作为最小值的最大范围.对于每个a[i],我们都要乘以一个以a[i]为区间内最小值的对应的b的区间和s,如果a[i] > 0,则s要 ...
- 2019牛客多校第四场K number dp or 思维
number 题意 给一个数字串,问有几个子串是300的倍数 分析 dp写法:这题一看就很dp,直接一个状态dp[i][j]在第i位的时候膜300的余数是j左过去即可.这题比赛的时候样例老是少1,后面 ...
随机推荐
- 【基本优化实践】【1.6】在sql server修改且移动数据库文件位置
在master数据库中,SQL Server提供系统扩展的存储过程,其中有一些存储过程的命名以xp_开头,用于处理操作系统的文件. 一,判断文件是否存在 存储过程sys.xp_fileexist 用于 ...
- K8S从入门到放弃系列-(3)部署etcd集群
摘要:etcd 是k8s集群最重要的组件,用来存储k8s的所有服务信息, etcd 挂了,集群就挂了,我们这里把etcd部署在master三台节点上做高可用,etcd集群采用raft算法选举Leade ...
- (九)Javabean与Jsp(来自那些年的笔记)
目录 JavaBean 在JSP中使用JavaBean 标签用法 带标签体的 JavaBean 标签 setProperty 标签 getProperty 标签 JSP开发模式 案列:使用 模式一 编 ...
- python 正则 re模块(详细版)
正则表达式 什么是正则表达式? 正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合 ...
- SAS学习笔记9 利用SAS绘制地图
绘制世界地图 proc gmap过程: map=指定绘图的map数据集 data=指定地图的对应数据集 id指定map数据集和对应数据集中都有的变量,一般为各区域的代码,作为两个数据集的连接变量 分色 ...
- THUPC2019/CTS2019/APIO2019游记
Day -? 居然还能报上thupc,我在队里唯一的作用大约是cfrating稍微高点方便过审.另外两位是lz和xyy. Day -2 我夫人生日! Day -1 lz和xyy的家长都来了带我飞.住在 ...
- 如何在含有json类型的字段上建立多列索引
废话不多,直接上图 如 : 表结构如图 那么我想在这三个字段上建立一个唯一索引,目的是为了防止重复插入数据, 1.首先,说明一下 data中的json中,key为 tagID 和 ...
- python打印表格式数据-星号或注释
python打印表格式数据,留出正确的空格,格式化打出 代码如下: def printPicnic(itemsDict,leftWidth,rightWidth): print('PICNIC ITE ...
- nodejs入门API之url模块+querystring模块
关于URL的一些基础内容 URL模块的API解析 URL的参数URLSearchParams类 querystring模块 一.关于URL的一些基础内容 1.1 定义: 在WWW上,每一信息资源都有统 ...
- 操作RDS文档说明
操作RDS文档,让你对阿里云的知识更加了解.