A1958
Magic Girl Haze
T组
n个点,m条有向含权边,可以选择不超过k条边,将其权值变为0.
问点1到点n的最短距离是多少?
1≤T≤5n≤105m≤2×105k≤10wi≤109
1\leq T \leq 5 \\
n \leq 10^5 \\
m \leq 2\times10^5 \\
k \leq 10 \\
w_i \leq 10^9
1≤T≤5n≤105m≤2×105k≤10wi≤109
二维状态Dijkstra
原本dijkstra算法是dis[v],只有点的编号一个维度,dis[v]状态表示的是1到v最短的距离。
现在令dis[k][v]表示恰好k条边变0,点1到v最短的距离,状态变为二维
原本是uuu到vvv有边就可以尝试状态转移
现在是
- (k,u)(k,u)(k,u)到(k,v)(k,v)(k,v)可以转移,代价w;
- (k,u)(k,u)(k,u)到(k+1,u)(k+1,u)(k+1,u)可以转移,代价0;
正确性是显然的:
对于状态k=k0,∀u(k,u)k = k_0,\forall u(k,u)k=k0,∀u(k,u),假设它们的初始值已经设置好了,则固定k=k0k=k_0k=k0,它们之间的转移更新就是传统的一维dijkstra,因此是正确的
k=k0,∀u(k,u)k = k_0,\forall u (k,u)k=k0,∀u(k,u)初始值本是无穷大, 但是k=K0−1k=K_0-1k=K0−1的状态可以优化它们的初始值。
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int t;
ll n, m;
int k;
const int maxn = 1e+5 + 5;
const int maxm = 2e+5 + 5;
const int maxk = 10;
vector<int> ev[maxn];
vector<ll> ew[maxn];
// bool solved[maxk + 1][maxn];
bool vis[maxk + 1][maxn];
ll dis[maxk + 1][maxn];
struct vnd
{
int v;
ll dis;
bool operator<(const struct vnd &obj) const
{
return dis > obj.dis;
}
void print() const {
cout << "(v,dis) = "<<v<<","<<dis<<endl;
}
};
priority_queue<vnd> q[maxk + 1];
void init()
{
cin >> n >> m >> k;
for (int u = 1; u <= n; ++u)
{
ev[u].clear();
ew[u].clear();
}
int u, v, w;
for (int i = 1; i <= m; ++i)
{
cin >> u >> v >> w;
ev[u].push_back(v);
ew[u].push_back(w);
}
// memset(solved, false, sizeof(solved));
memset(vis, false, sizeof(vis));
for (int i = 0; i <= k; ++i)
q[i] = priority_queue<vnd>();
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> t;
while (t--)
{
init();
bool first = true;
ll ans;
vis[0][1] = true;
dis[0][1] = 0;
int u, v;
ll w;
for (int i = 0; i <= k; ++i)
{
// push visited vertices into queue
for (int u = 1; u <= n; ++u)
if (vis[i][u]) {
q[i].emplace(vnd{u,dis[i][u]});
}
while (!q[i].empty())
{
vnd t = q[i].top();
q[i].pop();
u = t.v;
for (size_t j = 0; j < ev[u].size(); ++j)
{
v = ev[u][j];
w = ew[u][j];
// do not change w
if (!vis[i][v])
{
vis[i][v] = true;
dis[i][v] = t.dis + w;
q[i].emplace(vnd{v,dis[i][v]});
}
else if (dis[i][v] > t.dis + w)
{
dis[i][v] = t.dis + w;
q[i].emplace(vnd{v,dis[i][v]});
}
// change w to 0
if (i + 1 > k)
continue;
if (!vis[i + 1][v])
{
vis[i + 1][v] = true;
dis[i + 1][v] = t.dis;
}
else if (dis[i + 1][v] > t.dis)
{
dis[i + 1][v] = t.dis;
}
}
}
if (vis[i][n])
{
if (first)
{
first = false;
ans = dis[i][n];
}
else
{
ans = min(ans, dis[i][n]);
}
}
}
// the input ensure: first == false
cout << ans << endl;
}
return 0;
}
A1958的更多相关文章
- ICPC 2018 南京网络赛 J Magical Girl Haze(多层图最短路)
传送门:https://nanti.jisuanke.com/t/A1958 题意:n个点m条边的路,你有k次机会将某条路上的边权变为0,问你最短路径长度 题解:最短路变形,我们需要在常规的最短路上多 ...
随机推荐
- expect知识梳理
1 expect expect软件用于实现非交互式操作,实际应用中常用于批量部署,可以帮助运维人员管理成千上万台服务器. expect实现非交互式操作主要是在程序发出交互式询问时,按条件传递程序所需的 ...
- 前端开发:这10个Chrome扩展你不得不知
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://blog.bitsrc.io/10-top-chrome-extensions-f ...
- SpringMVC版本报错解决办法
报错代码: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http:// ...
- 初识matlab
1 matlab概貌 MATLAB是MATrix LABoratory(矩阵实验室)的缩写,是一款由美国The MathWorks公司出品的商业数学软件.matlab是一种用于算法开发.数据可视化.数 ...
- JDK SPI 机制
一.概述 最早看到 SPI 这个机制是在 dubbo 实现 中,最近发现原来也不是什么新东西,竟然就是 JDK 中内置的玩意,今天就来一探究竟,看看它到底是什么玩意! SPI的全称是 Service ...
- Spring Boot自动配置如何工作
通过使用Mongo和MySQL DB实现的示例,深入了解Spring Boot的@Conditional注释世界. 在我以前的文章“为什么选择Spring Boot?”中,我们讨论了如何创建Sprin ...
- 使用MuMu模拟器调试AndroidStudio项目
1.安装一款安卓模拟器 本例使用网易MuMu模拟器,因为目前网络上这类模拟器只有mumu的安卓版本是最新的,为6.0,安卓自带的Virtual Device虽然有很新的版本,但如果pc配置不是很高 ...
- App自动化测试环境搭建
只做记录和注意点,详细内容不做解释 环境:win+appium+夜神模拟器+python 需要用到的工具: 1.java JDK 2. node.js 3. Android SDK 4.Appium- ...
- clr via c# 接口
1,常用接口及其定义 public interface IDisposable{ void Dispose(); } public interface IEnumerable}{ IEnumerato ...
- mysql官方源安装的一些问题
今天测试Linux 各个软件源 ,发现mysql 配置官方源之后,yum install -y mysql 安装了 mysql lastst 最新版, 安装完之后,奇葩的是没有提示输入密码, 所 ...