给n点m边,L,s,t 修改m条边中边为0的边, 使满足s,t的最短路长度是L
很有意思
我们知道,每将一条边 +1,最多会使得最短路 L 的长度 +1
我们构造一个循环 +1 的操作序列,然后在这个操作序列上二分即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
struct Graph
{
int n, m;
vector<vector<pair<int, int>>> g;
void build(int n_, int m_)
{
n = n_;
m = m_;
g.resize(n + 2);
}
void make(int p, int q, int w)
{
g[p].push_back({q, w});
g[q].push_back({p, w});
}
int dijkstra(int s0, int t0)
{
struct Node
{
int d, p;
bool operator<(const Node &rhs) const
{
return d > rhs.d;
}
};
priority_queue<Node> que;
que.push({0, s0});
vector<int> d(n + 2, 1e18);
vector<int> v(n + 2, 0);
d[s0] = 0;
while (que.size())
{
auto [dis, p] = que.top();
que.pop();
if (v[p])
continue;
v[p] = 1;
for (auto [q, w] : g[p])
{
if (d[q] > d[p] + w)
{
d[q] = d[p] + w;
que.push({d[q], q});
}
}
}
return d[t0];
}
};
struct Solution
{
int n, m, l, s, t;
vector<tuple<int, int, int>> edge_static, edge_dynamic;
void read()
{
cin >> n >> m >> l >> s >> t;
++s;
++t;
for (int i = 1; i <= m; i++)
{
int t1, t2, t3;
cin >> t1 >> t2 >> t3;
++t1;
++t2;
if (t3 == 0)
edge_dynamic.push_back({t1, t2, t3});
else
edge_static.push_back({t1, t2, t3});
}
}
bool check(int k)
{
Graph graph;
graph.build(n, m);
if (edge_dynamic.size())
{
int a = k / edge_dynamic.size(), b = k % edge_dynamic.size();
for (int i = 0; i < edge_dynamic.size(); i++)
{
auto [u, v, w] = edge_dynamic[i];
if (i < b)
graph.make(u, v, w + a + 1);
else
graph.make(u, v, w + a);
}
}
for (auto [u, v, w] : edge_static)
{
graph.make(u, v, w);
}
int ans = graph.dijkstra(s, t);
// cout << "ans=" << ans << " but need " << l << endl;
if (ans < l)
return false;
return true;
}
bool check_strict(int k)
{
Graph graph;
graph.build(n, m);
if (edge_dynamic.size())
{
int a = k / edge_dynamic.size(), b = k % edge_dynamic.size();
for (int i = 0; i < edge_dynamic.size(); i++)
{
auto [u, v, w] = edge_dynamic[i];
if (i < b)
graph.make(u, v, w + a + 1);
else
graph.make(u, v, w + a);
}
}
for (auto [u, v, w] : edge_static)
{
graph.make(u, v, w);
}
int ans = graph.dijkstra(s, t);
// cout << "ans=" << ans << " but need " << l << endl;
if (ans != l)
return false;
return true;
}
void solve()
{
Graph graph;
graph.build(n, m);
for (auto [u, v, w] : edge_static)
{
graph.make(u, v, w);
}
for (auto [u, v, w] : edge_dynamic)
{
graph.make(u, v, w);
}
if (graph.dijkstra(s, t) > l)
{
cout << "NO" << endl;
}
else
{
int l = edge_dynamic.size(), r = 2e18;
while (l < r)
{
int mid = (l + r) / 2;
if (!check(mid))
l = mid + 1;
else
r = mid;
}
if (r > 1e18)
cout << "NO" << endl;
else
{
if (check_strict(r) == 0)
{
cout << "NO" << endl;
}
else
{
cout << "YES" << endl;
if (edge_dynamic.size())
{
int k = r;
int a = k / edge_dynamic.size(), b = k % edge_dynamic.size();
for (int i = 0; i < edge_dynamic.size(); i++)
{
auto [u, v, w] = edge_dynamic[i];
if (i < b)
cout << u - 1 << " " << v - 1 << " " << w + a + 1 << endl;
else
cout << u - 1 << " " << v - 1 << " " << w + a << endl;
}
}
for (auto [u, v, w] : edge_static)
{
cout << u - 1 << " " << v - 1 << " " << w << endl;
}
}
}
}
}
};
signed main()
{
ios::sync_with_stdio(false);
Solution solution;
solution.read();
solution.solve();
}
[CF715B] Complete The Graph - 最短路,二分
原文:https://www.cnblogs.com/mollnn/p/14453429.html