首页 > 其他分享 >CF715B Complete The Graph 题解

CF715B Complete The Graph 题解

时间:2024-11-18 20:22:26浏览次数:1  
标签:int 题解 det kMaxN vis Graph CF715B id dis

Description

给 \(n\) 点 \(m\) 边的无向图,\(L\),\(s\),\(t\)。

修改 \(m\) 条边中边为 \(0\) 的边,使满足 \(s,t\) 的最短路长度是 \(L\),且输出答案的时候边为 \(0\) 的边的权值必须在 \([1,10^{18}]\) 内。

Solution

考虑怎么判有无解。

容易发现将所有未知边边权设为 \(10^{18}\),如果最短路小于 \(L\),或者未知边设为 \(1\) 后最短路大于 \(L\) 时无解,否则有解。因为每次只将一条边的长度加 \(1\) 后最短路至多增加 \(1\)。

不妨设 \(dis_i\) 表示 \(i\) 在未知边边权为 \(1\) 时与 \(s\) 的距离,\(det\) 表示 \(L-dis_t\)。容易发现我们的任务就是让 \(dis_t\) 增加 \(det\)。

考虑再进行一次 dijkstra,如果当前松弛的边 \((u,v,w)\) 满足 \(dis_{v}+det>dis^{'}_{u}+w\) 且这条边未确定,就将 \(w\) 调整为 \(dis_{v}+det-dis^{'}_u\),这样的话每个点的最短路一定不会增加超过 \(det\),且 \(dis_t\) 一定能增加 \(det\)。

时间复杂度:\(O((n+m)\log n)\)。

Code

#include <bits/stdc++.h>

#define int int64_t

const int kMaxN = 1e3 + 5, kMaxM = 1e4 + 5;

int n, m, L, s, t, det;
int u[kMaxM], v[kMaxM], w[kMaxM];
int dis1[kMaxN], dis2[kMaxN];
bool del[kMaxM];
std::vector<std::tuple<int, int, int>> G[kMaxN];

int dijkstra1(int *dis) {
  static bool vis[kMaxN];
  for (int i = 1; i <= n; ++i) G[i].clear();
  for (int i = 1; i <= m; ++i) {
    if (w[i]) {
      G[u[i]].emplace_back(v[i], w[i], i), G[v[i]].emplace_back(u[i], w[i], i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    dis[i] = 1e18, vis[i] = 0;
  }
  std::priority_queue<std::pair<int, int>> q;
  q.emplace(0, s), dis[s] = 0;
  for (; !q.empty();) {
    int u = q.top().second; q.pop();
    if (vis[u]) continue;
    vis[u] = 1;
    for (auto [v, w, id] : G[u]) {
      if (dis[v] > dis[u] + w) {
        dis[v] = dis[u] + w;
        q.emplace(-dis[v], v);
      }
    }
  }
  return dis[t];
}

int dijkstra2(int *dis) {
  static bool vis[kMaxN];
  for (int i = 1; i <= n; ++i) G[i].clear();
  for (int i = 1; i <= m; ++i) {
    if (w[i]) {
      G[u[i]].emplace_back(v[i], w[i], i), G[v[i]].emplace_back(u[i], w[i], i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    dis[i] = 1e18, vis[i] = 0;
  }
  std::priority_queue<std::pair<int, int>> q;
  q.emplace(0, s), dis[s] = 0;
  for (; !q.empty();) {
    int u = q.top().second; q.pop();
    if (vis[u]) continue;
    vis[u] = 1;
    for (auto [v, w, id] : G[u]) {
      if (del[id] && dis1[v] + det > dis[u] + ::w[id])
        ::w[id] = dis1[v] + det - dis[u];
      if (dis[v] > dis[u] + ::w[id]) {
        dis[v] = dis[u] + ::w[id];
        q.emplace(-dis[v], v);
      }
    }
  }
  return dis[t];
}

void print() {
  std::cout << "YES\n";
  for (int i = 1; i <= m; ++i)
    std::cout << u[i] - 1 << ' ' << v[i] - 1 << ' ' << w[i] << '\n';
}

void dickdreamer() {
  std::cin >> n >> m >> L >> s >> t;
  ++s, ++t;
  for (int i = 1; i <= m; ++i) {
    std::cin >> u[i] >> v[i] >> w[i];
    ++u[i], ++v[i];
    if (!w[i]) del[i] = 1, w[i] = 1e18;
  }
  int dis = dijkstra1(dis1);
  if (dis < L) return void(std::cout << "NO\n");
  if (dis == L) return print();
  for (int i = 1; i <= m; ++i)
    if (del[i])
      w[i] = 1;
  int now = dijkstra1(dis1);
  if (now > L) return void(std::cout << "NO\n");
  det = L - now;
  dijkstra2(dis2);
  print();
}

int32_t main() {
#ifdef ORZXKR
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
#endif
  std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
  int T = 1;
  // std::cin >> T;
  while (T--) dickdreamer();
  // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
  return 0;
}

标签:int,题解,det,kMaxN,vis,Graph,CF715B,id,dis
From: https://www.cnblogs.com/Scarab/p/18553531

相关文章

  • ZZJC新生训练赛第17场题解
    难度分类(同一难度下按字典序上升)入门:J简单:G,E,D中等:I,B,k困难:F,AJ-解题思路按照题意模拟即可J-代码实现for_inrange(int(input())):print(int(int(input())**0.5))G-解题思路dp入门题跳台阶小改G-代码实现MOD=int(1e9+7)dp=[0]*in......
  • Codeforces Round 988 (Div. 3) E题解析
    E题题目链接CodeforcesRound988(Div.3)题目描述题目的思路根据题目的意思,我们可以推断出算法时间复杂度应该在O(N)对于这道题而言,我们可以分析下思路首先我们先从1~n的范围里面询问答案如果出现0就跳过,因为无序操作如果出现非0答案temp就记录下1~i的01序列的个数如果......
  • [HCTF 2018]Warmup 详细题解
    知识点:目录穿越_文件包含static静态方法参数传递引用mb_strpos函数    mb_substr函数正文:页面有一张滑稽的表情包,查看一下页面源代码,发现提示那就访问/source.php 得到源码<?phphighlight_file(__FILE__);classemmm{publics......
  • CF1499D The Number of Pairs 题解 线性筛
    题目链接:https://codeforces.com/problemset/problem/1499/D题目大意:给你三个整数\(c,d,x\)(\(1\lec,d,x\le10^7\)),问:存在多少对正整数对\((a,b)\)满足:\[c\cdotlcm(a,b)-d\cdotgcd(a,b)=x\]其中,\(lcm(a,b)\)表示整数\(a\)和\(b\)的最大公约数,\(gcd(a,......
  • [ABC380C] Move Segment 题解
    [ABC380C]MoveSegment题解本题主要考察思维能力,其实不难。题目大意给你一个字符串\(s\),\(s\)由\(0\)和\(1\)构成,将其分为块中只有一种数字的块。将给定的第\(k\)块数字为\(1\)的块与第\(k-1\)块合并,并输出修改后的字符串。思路分析直接按照题意模拟即可。建......
  • CF 705 题解
    CF705题解AHulk模拟即可.BSpiderMan打sg表可以发现,奇数个球先手必败(sg=0),偶数先手必胜(sg=1).多个组合只要把sg值异或起来就好.CThor暴力模拟就可以了,用队列模拟.DAntMan结论:按照编号由小到大加入链表,每次尽量让答案最小贪心就是对的.若原来是......
  • 企业级知识库为什么要用GraphRAG - 硅谷企业级ChatGPT独角兽Glean系列之二
    ArvindJain阿尔温德·贾恩CEO发布时间:2024年5月15日。最后更新日期2024年11月6日。自从生成式AI和LLM在世界舞台上占据中心位置以来,员工们一直在思考如何最好地将这些变革性的新工具应用于他们的工作流程。然而,他们中的许多人在尝试将生成式AI集成到......
  • CF1023题解
    CF1023A一眼秒之题因为整个s串至多有1个*号,所以可以把s串分为两个部分分别与t串的前后进行匹配,看看前后能不能适配即可注意特判没有*的情况CF1023B一眼秒之题+1简单的,就是一个数k拆成两个数之和,这两个数的值域为(1,n),分讨k为奇偶,然后简单转化即可CF1023C小清新一眼秒之题+1......
  • 题解:CF contest 2037 : [Codeforces Round 988 (Div. 3)] (A-E)
    ATwice题面Kinich醒来迎接新的一天的开始。他打开手机,查看邮箱,发现了一份神秘的礼物。他决定打开礼物的盒子。Kinich用\(n\)整数打开数组\(a\)。最初,Kinich的分数是\(0\)。他将执行任意次数的以下操作:—选择两个索引\(i\)和\(j\)\((1\leqi\lt;j\leqn)\),确......
  • 使用 PyTorch-BigGraph 构建和部署大规模图嵌入的完整教程
    当涉及到图数据时,复杂性是不可避免的。无论是社交网络中的庞大互联关系、像Freebase这样的知识图谱,还是推荐引擎中海量的数据量,处理如此规模的图数据都充满挑战。尤其是当目标是生成能够准确捕捉这些关系本质的嵌入表示时,更需要一种不会在庞大数据量下崩溃的解决方案。PyTorch......