「CF716D」Complete The Graph「最短路」
题意
给定一个\(n\)个点\(m\)条边的无向图,有一些边权暂时为\(0\),你需要分配一个\([1, 10^{18}]\)的数。最终使得\(s\)到\(t\)最短路为\(L\),输出一个可行的分配方案,或告知无解。
\(n \leq 10^3\),\(m \leq 10^4\),\(L \leq 10^9\)
题解
首先拿到这个图,我们把\(0\)边换成INF,求\(s\)到\(t\)的最短路\(d\),如果此时\(d<L\),则无解
再把\(0\)边换成\(1\),求最短路\(d\),如果\(d>L\),也无解
上面两行是显然的,我们现在证明除了以上情况,一定有解。
考虑把\(0\)边换\(1\)。然后所有\(s\)到\(t\)的路径拿出来按权值从小到大排序,这时第一条路径\(d\leq L\)。若\(d=L\)则结束,否则这条路径一定含有可变边。把可变边+1(这可能导致一些路径权值+1)。重复上述过程就能得到解。
那么第一种做法:我们用和证明相似的做法来求解。把\(0\)边换\(1\)后,我们找一条任意最短路径。我们直接把不在这路径上的可变边变成INF并固定,不需要考虑。这样一定是对的。不经过可变边的路径>L,经过非标记可变边的路径=inf,只剩下经过标记边的路径要考虑。
那么我们每次跑一下最短路,找到最短路上一个标记边,然后加上\(L-d\)并固定。这样进行若干次一定能出解。容易看出最多n次(标记边数量是\(O(n)\)的),这个复杂度\(O(nm\log n)\)
CF上还给了一个优秀解法,具体看:http://codeforces.com/blog/entry/47169
upd:研究了一下上面那个2遍dijkstra的做法,大概意思就是现在\(d[t]\)缺少\(x\),就把每个\(d\)都能加的都加\(x\)(指的是最终的\(d = d + x\)),这样原边顺延,\(d[t]\)也就加了\(x\)
另外在民间发现二分解法,非常易懂,应该是理解起来最简单的做法:https://www.cnblogs.com/zhouzhendong/p/CF715B.html
代码:(解法1)
#include <algorithm>
#include <vector>
#include <cstdio>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 1e3 + 10;
const int M = 2e4 + 10;
const ll INF = 1e16;
struct Edge {
int v, nxt; ll w;
} e[M];
int hd[N], p, n, m, L, s, t, pre[N];
bool use[M], mark[M];
vector<int> mdf, mmdf;
void clr() { fill(hd, hd + n, -1); p = 0; }
void add(int u, int v, ll w) {
e[p] = (Edge) {v, hd[u], w}; hd[u] = p ++;
}
struct node {
int u; ll d;
bool operator < (const node &b) const { return d > b.d; }
};
ll d[N];
ll dijkstra() {
fill(d, d + n, INF * 10ll);
priority_queue<node> pq; pq.push((node) {s, d[s] = 0});
while(pq.size()) {
node k = pq.top(); pq.pop();
int u = k.u; ll du = k.d;
if(d[u] < du) continue ;
for(int i = hd[u]; ~ i; i = e[i].nxt) {
Edge &g = e[i];
if(d[g.v] > d[u] + g.w) {
pre[g.v] = i;
pq.push((node) {g.v, d[g.v] = d[u] + g.w});
}
}
}
return d[t];
}
int main() {
scanf("%d%d%d%d%d", &n, &m, &L, &s, &t); clr();
for(int i = 0; i < m; i ++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
if(w == 0) mdf.push_back(p), use[p] = 1;
add(u, v, w); add(v, u, w);
}
for(int i = 0; i < mdf.size(); i ++) {
int j = mdf[i]; e[j].w = e[j ^ 1].w = INF;
}
if(dijkstra() < L) return puts("NO"), 0;
for(int i = 0; i < mdf.size(); i ++) {
int j = mdf[i]; e[j].w = e[j ^ 1].w = 1;
}
if(dijkstra() > L) return puts("NO"), 0;
puts("YES");
for(int u = t; u != s; u = e[pre[u] ^ 1].v) {
int j = pre[u], v = e[j ^ 1].v; j >>= 1; j <<= 1;
if(use[j] && d[u] == d[v] + e[j].w || d[v] == d[u] + e[j].w) {
mark[j] = 1; mmdf.push_back(j);
}
}
for(int i = 0; i < mdf.size(); i ++) {
int j = mdf[i];
if(!mark[j]) e[j].w = e[j ^ 1].w = INF;
}
while(1) {
ll di = dijkstra();
if(di == L) break ;
for(int i = 0; i < mmdf.size(); i ++) {
int j = mmdf[i];
if(mark[j]) {
mark[j] = 0; e[j].w += L - di; e[j ^ 1].w += L - di; break ;
}
}
}
for(int i = 0; i < p; i += 2)
printf("%d %d %I64d\n", e[i ^ 1].v, e[i].v, e[i].w);
return 0;
}
「CF716D」Complete The Graph「最短路」的更多相关文章
- Codeforces 715B & 716D Complete The Graph 【最短路】 (Codeforces Round #372 (Div. 2))
B. Complete The Graph time limit per test 4 seconds memory limit per test 256 megabytes input standa ...
- 「AGC034E」 Complete Compress
「AGC034E」 Complete Compress 显然可以枚举根. 然后把某两棵棋子同时往深度浅的方向提,即对不存在祖先关系的两个棋子进行操作. 如果能到达那么就更新答案. 问题转化为如何判定能 ...
- FileUpload控件「批次上传 / 多档案同时上传」的范例--以「流水号」产生「变量名称」
原文出處 http://www.dotblogs.com.tw/mis2000lab/archive/2013/08/19/multiple_fileupload_asp_net_20130819. ...
- 「前端开发者」如何把握住「微信小程序」这波红利?
由于前两周一直在老家处理重要事情,虽然朋友圈被「微信小程序」刷爆了,但并没有时间深入了解. 昨天回广州之后,第一件事情就是把「微信小程序」相关的文章.开发文档.设计规范全部看了一遍,基本上明白了「微信 ...
- SQL Server 2016 的「動態資料遮罩 (Dynamic Data Masking)」
一些特別注重資訊安全.個人資料的公司或產業 (如: 金融.保險業),通常「測試用資料庫」的資料,會加上「遮蔽:去識別化」的功能,避免個資外洩.以往必須自己撰寫 SQL 語句或 Stored Proce ...
- Linux 小知识翻译 - 「Linux的吉祥物企鹅叫什么名字?」
这次说说Linux的吉祥物 *企鹅* 都知道Linux的吉祥物是企鹅,但是这个企鹅叫什么名字呢? 它的名字就是「Tux」,注意可不是「Tax」(税收). 具体参考 wiki:中文解释 英文的解释更为 ...
- LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set(线性基,贪心)
LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set $ solution: $ 这一题的重点在于优先级问题,我们应该先保证总和最大,然后再保证某一个最小.于是我 ...
- 「 从0到1学习微服务SpringCloud 」10 服务网关Zuul
系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」06 统一配置中心Spring Cloud Config 「 从0到1学习微服务SpringCloud 」07 RabbitM ...
- 「 从0到1学习微服务SpringCloud 」09 补充篇-maven父子模块项目
系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」06 统一配置中心Spring Cloud Config 「 从0到1学习微服务SpringCloud 」07 RabbitM ...
随机推荐
- Hibernate一对多自关联、多对多关联
今天分享hibernate框架的两个关联关系 多对多关系注意事项 一定要定义一个主控方 多对多删除 主控方直接删除 被控方先通过主控方解除多对多关系,再删除被控方 禁用级联删除 关联关系编辑,不 ...
- [eclipse]UML之AmaterasUML 插件
软件体系结构分析软件设计模式要求给出相应设计模式源码对应的UML类图,在此之前我安装过一种UML插件,可以自动生成一个源码包对应的UML类图,但是重装过系统,所以软件包括eclipse都重新下载了新的 ...
- 音视频入门-01-认识RGB
* 音视频入门文章目录 * RGB 简介 RGB 色彩模式是工业界的一种颜色标准,是通过对红(R).绿(G).蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB 即是代表红 ...
- CentOS7/RHEL6下,如何查看目录与子目录大小
原文:CentOS7/RHEL6下,如何查看目录与子目录大小 通过强大的[du]命令,可以帮助我们快捷的查看目录的大小,非常实用. du命令用来查看目录或文件所占用磁盘空间的大小.常用选项组合为:du ...
- JS原型的动态性
由于在原型中查找成员的过程是一次搜索,所以我们对原型对象所做的任何修改都能立即从实例上反映出来(但不包括对原型对象的重写,下面会介绍到),即使是对原型的修改操作在创建实例之后.如下面的示例所示: fu ...
- linux 添加硬盘找不到使用/sys/class/scsi_host/host/scan
添加磁盘到dg--首先通知存储管理员划分相应的盘到指定的机器,说明共享--扫描磁盘(两个节点执行)[root@testrac1 ~]# echo "- - -" > /sys ...
- python处理RSTP视频流
python链接海康摄像头,并以弹出框的方式播放实时视频流, 这种方式是以弹出框的形式播放.本地测试可以,实际业务场景不建议使用.可以采用rtsp转rtmp的方式 @shared_task def p ...
- element的Dialog组件踩坑
在一个组件页面中需要有一个弹窗,为了代码简洁我把弹窗封装成一个组件方便重复调用 描述大致是一个父组件,里面有一个按钮还有一个子组件(弹窗),点击按钮让弹窗出来,弹窗自带的有关闭功能,点击关闭以后再点击 ...
- XCode5环境下利用crash log调试线上Crash的流程
1.前言 本文主要介绍在XCode5环境下,如何根据App自己生成的crashlog来调试真机上运行时产生的crash问题. 2. 步骤 (1)构造一段会crash的代码,并放到viewDidLoad ...
- laravel中引入composer安装在vendor中的第三方组件
一.安装第三方组件 方法一:使用命令行安装第三方(已phpword为例): composer require phpoffce/phpword ^v0..* 方法二: 修改主项目composer.js ...