大型补档计划

题目链接

这题是求必须边,而不是不可行边,因为不可行边 = 必须边 + 死掉了的边(貌似lyd第三版书上还是说的不可行边)先跑最大流。

在跑完以后的残余网络上,对于一条当前匹配的边 \((u, v)\),对应流量为 \(1\),只有他们有可能是必须边。

考虑断开这条边,能否找到增广路,如果能就是可行边,否则是必须边。

新的增广路的端点一定是 \(u, v\) 中的一个,否则即有更大的最大流。

接下来分类讨论。

  1. 若是找到一条 (u, v) 的路径且不包括 t,则可以把增广路上的边全部取反,就得到了一组新的答案。

  2. 若是一个点 u 找到了它的非匹配点 z, 由于 \(w(z, t) = 1, w(t, v) = 0\),所以 \((u, v)\) 还是构成一个环,包括 t

如果两点都不满足,必然不成环,所以就用 tarjan 算法缩点以后判断在不在一个强连通分量即可。

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cstring>
  4. using namespace std;
  5. const int N = 20005, S = 400005, INF = 1e9;
  6. int n, m, T, s, t, q[N], d[N];
  7. int dfn[N], low[N], dfncnt;
  8. int col[N], cnt = 0, st[N], top;
  9. bool ins[N];
  10. struct E{
  11. int next, v, w;
  12. } e[S];
  13. int head[N], numE = 1;
  14. void inline add(int u, int v, int w) {
  15. e[++numE] = (E) { head[u], v, w };
  16. head[u] = numE;
  17. }
  18. bool bfs() {
  19. memset(d, 0, sizeof d);
  20. int hh = 0, tt = 0;
  21. q[0] = s; d[s] = 1;
  22. while (hh <= tt) {
  23. int u = q[hh++];
  24. for (int i = head[u]; i; i = e[i].next) {
  25. int v = e[i].v;
  26. if (e[i].w && !d[v]) {
  27. d[v] = d[u] + 1;
  28. q[++tt] = v;
  29. if (v == t) return true;
  30. }
  31. }
  32. }
  33. return false;
  34. }
  35. int dinic(int u, int flow) {
  36. if (u == t) return flow;
  37. int rest = flow;
  38. for (int i = head[u]; i && rest; i = e[i].next) {
  39. int v = e[i].v;
  40. if (e[i].w && d[v] == d[u] + 1) {
  41. int k = dinic(v, min(rest, e[i].w));
  42. if (!k) d[v] = 0;
  43. e[i].w -= k, e[i ^ 1].w += k;
  44. rest -= k;
  45. }
  46. }
  47. return flow - rest;
  48. }
  49. bool tarjan(int u) {
  50. dfn[u] = low[u] = ++dfncnt;
  51. ins[u] = true, st[++top] = u;
  52. for (int i = head[u]; i; i = e[i].next) {
  53. int v = e[i].v;
  54. if (!e[i].w) continue;
  55. if (!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]);
  56. else if (ins[v]) low[u] = min(low[u], dfn[v]);
  57. }
  58. if (dfn[u] == low[u]) {
  59. int v; ++cnt;
  60. do {
  61. v = st[top--];
  62. ins[v] = false;
  63. col[v] = cnt;
  64. } while (v != u);
  65. }
  66. }
  67. int main() {
  68. scanf("%d%d%d", &n, &m, &T);
  69. s = n + m + 1, t = n + m + 2;
  70. for (int i = 1, u, v; i <= T; i++) {
  71. scanf("%d%d", &u, &v);
  72. add(u, v + n, 1); add(v + n, u, 0);
  73. }
  74. for (int i = 1; i <= n; i++) add(s, i, 1), add(i, s, 0);
  75. for (int i = 1; i <= m; i++) add(n + i, t, 1), add(t, n + i, 0);
  76. while (bfs() && dinic(s, INF));
  77. for (int i = 1; i <= t; i++)
  78. if (!dfn[i]) tarjan(i);
  79. int ans = 0;
  80. for (int i = 2; i <= 2 * T; i += 2)
  81. if (e[i].w && col[e[i].v] != col[e[i ^ 1].v]) ans++;
  82. printf("%d\n", ans);
  83. if (!ans) puts("");
  84. for (int i = 2; i <= 2 * T; i += 2)
  85. if (e[i].w && col[e[i].v] != col[e[i ^ 1].v]) printf("%d ", i >> 1);
  86. }

AcWing 380. 舞动的夜晚的更多相关文章

  1. CH Round #17 舞动的夜晚

    舞动的夜晚 CH Round #17 描述 L公司和H公司举办了一次联谊晚会.晚会上,L公司的N位员工和H公司的M位员工打算进行一场交际舞.在这些领导中,一些L公司的员工和H公司的员工之间是互相认识的 ...

  2. CH#17C 舞动的夜晚

    原题链接 即求二分图的不可行边数量,因为不保证是完备匹配,所以需要通过网络流求出任意一组最大匹配,并建立新图判断. 建新图:对于跑完网络流的图上已经匹配的边,建立反边:对于没有匹配的边,建立正边(图只 ...

  3. ContestHunter#17-C 舞动的夜晚

    Description: L公司和H公司举办了一次联谊晚会.晚会上,L公司的N位员工和H公司的M位员工打算进行一场交际舞.在这些领导中,一些L公司的员工和H公司的员工之间是互相认识的,这样的认识关系一 ...

  4. [Contest Hunter#17-C] 舞动的夜晚

    [题目链接] http://contest-hunter.org:83/contest/CH%20Round%20%2317/%E8%88%9E%E5%8A%A8%E7%9A%84%E5%A4%9C% ...

  5. 二分图&网络流初步

    链接 : 最小割&网络流应用 EK太低级了,不用. 那么请看:#6068. 「2017 山东一轮集训 Day4」棋盘,不用EK你试试? dinic模板及部分变形应用见zzz大佬的博客:网络流学 ...

  6. 0x6A 网络流初步

    CH Round #17-C 这个算是一个技能点吧,不点不会,点了就没什么了.懒得写看书吧书上的1应该是0... 我又回来了太懒了不想翻书还是写写吧 必须边的判定条件:该边流量为0且两端的点在残余网络 ...

  7. [考试反思]1019csp-s模拟测试80(a):天遣

    A组题,所以把榜粘全了. 第6名,被卡在刚好正中间. 我最近干什么伤天害理的事了?(例如说没有在skyh去上厕所的时候捶他) 上来看T1,非常贴心出题人直接把递推式子给你了,然后就和斐波数的递推一样了 ...

  8. Noip模拟58 2021.9.21(中秋祭&&换机房祭)

    第一次在学校过中秋节,给家里人视频电话,感觉快回家了很开心, 然后还吃了汉堡喝饮料非常爽,颓废了一会儿还换了新机房,$Linux2.0$非常dei,少爷机也非常快, 发现好像测评机又成了老爷机,这就是 ...

  9. 2021.9.21考试总结[NOIP模拟58]

    T1 lesson5! 开始以为是个无向图,直接不懂,跳去T2了. 之后有看了一眼发现可暴力,于是有了\(80pts\). 发现这个图是有拓扑序的,于是可以用拓扑排序找最长路径.先找原图内在最长路径上 ...

随机推荐

  1. python-redmine获取redmine平台的信息

    前言 最近做redmine的bug平台的分析,统计一些需要用到的数据,这里把相关调用的地方记录下来以备后用 相关的获取接口 #! /usr/bin/python # -*- coding:UTF-8 ...

  2. linux下内存释放

    细心的朋友会注意到,当你在linux下频繁存取文件后,物理内存会很快被用光,当程序结束后,内存不会被正常释放,而是一直作为caching.这个问题,貌似有不少人在问,不过都没有看到有什么很好解决的办法 ...

  3. Linux(CentOS6.8)配置Redis

    1.Redis简介 Redis:REmote DIctionary Server(远程字典服务器). Redis是完全开源免费的,用C语言编写的,遵守BSD协议,是一个高性能的(key/value)分 ...

  4. 每天一个linux命令之top

    每天一个linux命令之top 转  https://www.linuxprobe.com/chapter-02.html 在图2-6中,top命令执行结果的前5行为系统整体的统计信息,其所代表的含义 ...

  5. 实验吧[WEB]——程序逻辑问题

    拿到题 通过查看网页源代码发现index.txt 通过index.txt我们获得了后端的源代码 我们可以通过我画出来的这两个重要的信息得知 第一个sql查询语句没有任何过滤说明存在SQL注入漏洞. 第 ...

  6. 使用pdfFactory隐藏文档中的隐私信息

    分享PDF文档时,文档中可能会存在一些隐私信息,比如用户名.用户的邮件地址.电话号码等信息.为了更好地保护原有文档内容的完整性,大家可以在生成PDF时,使用pdfFactory的隐藏信息功能,删除或遮 ...

  7. C语言讲义——传值、传引用

    传值 值类型在做参数的时候,函数内使用的是实参的副本. 函数执行完毕后,即使函数内对参数做了修改,调用方的参数还是原来的值. #include <stdio.h> // 值调用 void ...

  8. python应用(4):变量与流程

    程序是什么?就是一堆代码啰.但是代码是有组织而来的,不是凭空堆砌出来的.有一个"古老"的说法:程序=数据结构+算法,意思是,程序是由一些数据结构(数据的组织结构)加上某些算法而形成 ...

  9. Java安全之JNI绕过RASP

    Java安全之JNI绕过RASP 0x00 前言 前面一直想看该JNI的相关内容,但是发现JNI的资料还是偏少.后面发现JNI在安全中应用非常的微妙,有意思. 0x01 JNI概述 JNI的全称叫做( ...

  10. springboot补充

    springboot中的日志: 在默认的spring-boot-starter中,会引入spring-boot-starter-logging, 而springboot-starte-longing中 ...