CF715B. Complete The Graph

题意:

给一张 n 个点,m 条边的无向图,要求设定一些边的边权

使得所有边权都是正整数,最终 S 到 T 的最短路为 L

1 ≤ n ≤ 1000, 1 ≤ m ≤ 10000


假做法:

spfa求s到t最短路且满足可变边最少

然后把不在最短路上的可变边标为inf,最短路上的可变边修改成使最短路长为L

假的原因:

其他的赋值为inf只是保证了经过其他可变边的路径不会更短,没有保证不经过其他可变边只是少经过了几条可变边、导致比最短路长的路径不会在最短路修改后更短

存在绕过某条可变边的路径p,本来不是最短路且不经过最短路上可变边x,但你修改x之后,p会变成当前最短路,于是这个做法就挂掉了。

就是说走了非可变边,把你修改的那条可变边绕过去了

修正:

真做法1:

应当选择满足d<L的路径中经过可变边最少的一条

可以在最短路上加维,\(d(i,j)\)表示1到i经过j条可变边的最短路

复杂度\(O(mn\log{mn})\)

真做法2:

随便求一条最短路,同样其他赋值inf,然后枚举最短路上的可变边,依次修改改可变边的值,修改后再求最短路看看会不会被绕过去。最后一定会收敛出答案

无解:不经过可变边就可以<L,经过可变边也比L大

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
const int N = 1e5+5, M = 1e6+5;
const ll inf = 1e16; int n, m, L, s, t;
struct edge {int u, v, ne; ll w;} e[M];
struct meow {int u, v; ll w;} a[M];
int cnt=1, h[N], mark[M];
inline void ins(int u, int v, ll w) {
if(w == 0) w=1, mark[cnt+1] = mark[cnt+2] = 1;
e[++cnt] = (edge) {u, v, h[u], w}; h[u] = cnt;
e[++cnt] = (edge) {v, u, h[v], w}; h[v] = cnt;
a[cnt>>1] = (meow) {u, v, w};
}
inline void paint(int x, ll v) {
a[x].w = v;
e[x<<1].w = e[x<<1|1].w = v;
} ll d[N];
int inq[N], pre[N];
int q[N], head, tail;
inline void lop(int &x) {if(x==N) x = 1;}
void spfa0(int s) {
memset(d, 0x3f, sizeof(d));
head = tail = 1;
d[s] = 0; q[tail++] = s; inq[s] = 1;
while(head != tail) {
int u = q[head++]; lop(head); inq[u] = 0;
for(int i=h[u]; i; i=e[i].ne) if(!mark[i]) {
int v = e[i].v;
if(d[v] > d[u] + e[i].w) {
d[v] = d[u] + e[i].w;
if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
}
}
}
} void spfa(int s) {
memset(d, 0x3f, sizeof(d));
memset(inq, 0, sizeof(inq));
head = tail = 1;
d[s] = 0; q[tail++] = s; inq[s] = 1;
while(head != tail) {
int u = q[head++]; lop(head); inq[u] = 0;
for(int i=h[u]; i; i=e[i].ne) {
int v = e[i].v;
if(d[v] > d[u] + e[i].w ) {
d[v] = d[u] + e[i].w;
pre[v] = i;
if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
}
}
}
}
int chose[N];
vector<int> li;
int main() {
//freopen("in", "r", stdin);
ios::sync_with_stdio(false); cin.tie(); cout.tie();
cin >> n >> m >> L >> s >> t;
s++; t++;
for(int i=1; i<=m; i++) {
int u, v, w;
cin >> u >> v >> w;
u++; v++;
ins(u, v, w);
}
spfa0(s);
if(d[t] < L) {cout << "NO"; return 0;}
spfa(s);
if(d[t] > L) {cout << "NO"; return 0;}
if(d[t] == L) {
cout << "YES" << endl;
for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '\n';
return 0;
} int x = t;
while(x != s) {
if(mark[pre[x]]) chose[pre[x]>>1] = 1, li.push_back(pre[x]>>1);
x = e[pre[x]].u;
}
for(int i=1; i<=cnt>>1; i++) if(mark[i<<1] && !chose[i]) paint(i, inf);
for(int i=0; i<li.size(); i++) {
int now = li[i];
int delta = L - d[t] + 1;
paint(now, delta);
spfa(s);
if(d[t] == L) break;
}
cout << "YES" << endl;
for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '\n';
}

ps:假做法的代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 1e5+5, M = 1e6+5;
const ll inf = 1e16; int n, m, L, s, t;
struct edge {int u, v, ne; ll w;} e[M];
struct meow {int u, v; ll w;} a[M];
int cnt=1, h[N], mark[M];
inline void ins(int u, int v, ll w) {
if(w == 0) w=1, mark[cnt+1] = mark[cnt+2] = 1;
e[++cnt] = (edge) {u, v, h[u], w}; h[u] = cnt;
e[++cnt] = (edge) {v, u, h[v], w}; h[v] = cnt;
a[cnt>>1] = (meow) {u, v, w};
} ll d[N];
int inq[N], cou[N], pre[N];
int q[N], head, tail;
inline void lop(int &x) {if(x==N) x = 1;}
void spfa0(int s) {
memset(d, 0x3f, sizeof(d));
head = tail = 1;
d[s] = 0; q[tail++] = s; inq[s] = 1;
while(head != tail) {
int u = q[head++]; lop(head); inq[u] = 0;
for(int i=h[u]; i; i=e[i].ne) if(!mark[i]) {
int v = e[i].v;
if(d[v] > d[u] + e[i].w) {
d[v] = d[u] + e[i].w;
if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
}
}
}
}
namespace test {
int pre[N];
void spfa1(int s) {
memset(d, 0x3f, sizeof(d));
head = tail = 1;
d[s] = 0; q[tail++] = s; inq[s] = 1;
while(head != tail) {
int u = q[head++]; lop(head); inq[u] = 0;
for(int i=h[u]; i; i=e[i].ne) {
int v = e[i].v;
if(d[v] > d[u] + e[i].w) {
d[v] = d[u] + e[i].w;
pre[v] = i;
if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
}
}
}
}
}
void spfa(int s) {
memset(d, 0x3f, sizeof(d));
memset(cou, 0x3f, sizeof(cou));
memset(inq, 0, sizeof(inq));
head = tail = 1;
d[s] = 0; cou[s] = 0; q[tail++] = s; inq[s] = 1;
while(head != tail) {
int u = q[head++]; lop(head); inq[u] = 0;
for(int i=h[u]; i; i=e[i].ne) {
int v = e[i].v;
if(d[v] > d[u] + e[i].w || (d[v] == d[u]+e[i].w && cou[v] > cou[u] + mark[i])) {
d[v] = d[u] + e[i].w;
cou[v] = cou[u] + mark[i];
pre[v] = i;
if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
}
}
}
}
int chose[N];
int main() {
//freopen("in", "r", stdin);
ios::sync_with_stdio(false); cin.tie(); cout.tie();
cin >> n >> m >> L >> s >> t;
s++; t++;
for(int i=1; i<=m; i++) {
int u, v, w;
cin >> u >> v >> w;
u++; v++;
ins(u, v, w);
}
spfa0(s);
if(d[t] < L) {cout << "NO"; return 0;}
spfa(s);
if(d[t] > L) {cout << "NO"; return 0;}
if(d[t] == L) {
cout << "YES" << endl;
for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '\n';
return 0;
} int x = t;
int flag = 0;
while(x != s) {
if(mark[pre[x]]) chose[pre[x]>>1] = 1, flag = pre[x] >> 1;
x = e[pre[x]].u;
}
if(!flag) {cout << "NO"; return 0;}
for(int i=1; i <= cnt>>1; i++) if(mark[i<<1] && !chose[i]) a[i].w = inf;
for(int i=1; i<=cnt; i++) if(mark[i] && !chose[i>>1]) e[i].w = inf;
int delta = L - d[t] + 1;
a[flag].w = delta;
e[flag<<1].w = e[flag<<1|1].w = delta; test::spfa1(s);
if(d[t] != L) {
cout << d[t] << "nooooo\n";
int x = t;
while(x != s) {
if(test::pre[x] != pre[x]) {
cout << "wrong\n";
cout << mark[pre[x]] << " " << mark[test::pre[x]] << '\n';
}
x = e[pre[x]].u;
}
}
cout << "YES" << endl;
for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '\n';
}

CF715B. Complete The Graph的更多相关文章

  1. 【图论 思维】cf715B. Complete The Graph加强

    zzq讲的杂题 题目大意 有一张$n​$个点$m​$条边的简单正权无向图,$S​$到$T​$的最短路为$L​$,现在有一些边的边权未知,请输出任意一种满足题意的方案. $n,m\le 500000​$ ...

  2. 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 ...

  3. 【Codeforces】716D Complete The Graph

    D. Complete The Graph time limit per test: 4 seconds memory limit per test: 256 megabytes input: sta ...

  4. CodeForces 715B Complete The Graph 特殊的dijkstra

    Complete The Graph 题解: 比较特殊的dij的题目. dis[x][y] 代表的是用了x条特殊边, y点的距离是多少. 然后我们通过dij更新dis数组. 然后在跑的时候,把特殊边都 ...

  5. Codeforces 715B. Complete The Graph 最短路,Dijkstra,构造

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF715B.html 题解 接下来说的“边”都指代“边权未知的边”. 将所有边都设为 L+1,如果dis(S,T ...

  6. codeforces 715B:Complete The Graph

    Description ZS the Coder has drawn an undirected graph of n vertices numbered from 0 to n - 1 and m ...

  7. 「CF716D」Complete The Graph「最短路」

    题意 给定一个\(n\)个点\(m\)条边的无向图,有一些边权暂时为\(0\),你需要分配一个\([1, 10^{18}]\)的数.最终使得\(s\)到\(t\)最短路为\(L\),输出一个可行的分配 ...

  8. Codeforces Round #372 (Div. 1) B. Complete The Graph (枚举+最短路)

    题目就是给你一个图,图中部分边没有赋权值,要求你把无权的边赋值,使得s->t的最短路为l. 卡了几周的题了,最后还是经群主大大指点……做出来的…… 思路就是跑最短路,然后改权值为最短路和L的差值 ...

  9. Codeforces715 B. Complete The Graph

    传送门:>Here< 题意:给出一张带权无向图,其中有一些边权为0.要求将边权为0的边的边权重置为一个任意的正整数,使得从S到T的最短路为L.判断是否存在这种方案,如果存在输出任意一种 解 ...

随机推荐

  1. webpack配置less

    webpack4.0把webpack.config.js隐藏起来了,需要先暴露出来,在webpack修改配置

  2. 动态解析xml,并生成excel,然后发邮件。

    直接贴代码了! DECLARE @CurrentServer NVARCHAR(100)DECLARE @CurrentDatabase NVARCHAR(100)DECLARE @CurrentLo ...

  3. Ubuntu 18.04 记录

    登录后死机,关机时死机的解决方法 更新内核并安装 Nvidia 显卡驱动可解决. 在内核更新为 4.15.18,Nvidia 显卡驱动为 390 时,问题解决. 使用 LiveCD 启动,然后 mou ...

  4. python面试题一个字符串是否由重复的子字符串组成

    一,给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成.给定的字符串只含有小写英文字母,并且长度不超过10000. 输入: "abab" 输出: True 解释: 可由 ...

  5. 一、下载安装superset

    1.环境介绍: 操作系统:Windows 10 python版本:3.73 2.创建虚拟环境: 打开命令行窗口,使用安装python自带的pip命令,下载pinenv 虚拟环境工具, pip inst ...

  6. Excel如何快速统计一列中相同数值出现的个数--数据透视表

    excel如何快速统计一列中相同数值出现的个数_百度经验 --这里介绍了两种解决方式,用第一种https://jingyan.baidu.com/article/9113f81b2c16822b321 ...

  7. Win10蓝屏的一些解决办法

    请仔细回想这个错误是什么时候出现的: 第一次发生时你对系统做了哪些操作: 发生时正在进行什么操作: 从这些信息中找出可能的原因: 从而选择相应解决方案并尝试排除. 0x0000000A:IRQL_NO ...

  8. CF1153C Serval and Parenthesis Sequence

    题目地址:CF1153C Serval and Parenthesis Sequence 思路:贪心 如果有解,那么 \(s_0 = (\) && \(s_{n-1} = )\) &a ...

  9. 基于注解的SpringMVC自定义DispatcherServlet配置

    通过重载AbstractAnnotationConfigDispatcherServletInitializer实现类的customizeRegistration()方法来自定义DispatcherS ...

  10. hyperledger fabric部署总结

    之前在有道云笔记上分享过,但想想还是搬到这里来吧,以后统一方便整理自己的知识进入正题.... 之前在调研 hyperledger fabric,其实部署说明官网都有,只是东西都是国外的照着操作也会遇到 ...