P2764 最小路径覆盖问题

这个题目之前第一次做的时候感觉很难,现在好多了,主要是二分图定理不太记得了,二分图定理

知道这个之后就很好写了,首先我们对每一个点进行拆点,拆完点之后就是跑最大流,求出最大匹配数,

然后就可以求出最小路径覆盖数,这个题目的难点在于求路径,其实很好写,就是用一个数组来写就可以了。

每一个点都记录一下它下一个点是哪个位置,最后把拆开了的点合并就可以了。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <string>
#include <iostream>
#include <vector>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 3e5 + ;
typedef long long ll;
struct edge {
int u, v, c, f;
edge(int u, int v, int c, int f) :u(u), v(v), c(c), f(f) {}
};
vector<edge>e;
vector<int>G[maxn];
int level[maxn];//BFS分层,表示每个点的层数
int iter[maxn];//当前弧优化
int m;
bool tag[maxn];
int to[maxn];
void init(int n) {
for (int i = ; i <= n; i++)G[i].clear();
e.clear();
}
void addedge(int u, int v, int c) {
e.push_back(edge(u, v, c, ));
e.push_back(edge(v, u, , ));
m = e.size();
G[u].push_back(m - );
G[v].push_back(m - );
}
void BFS(int s)//预处理出level数组
//直接BFS到每个点
{
memset(level, -, sizeof(level));
queue<int>q;
level[s] = ;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v = ; v < G[u].size(); v++) {
edge& now = e[G[u][v]];
if (now.c > now.f && level[now.v] < ) {
level[now.v] = level[u] + ;
q.push(now.v);
}
}
}
}
int dfs(int u, int t, int f)//DFS寻找增广路
{
if (u == t)return f;//已经到达源点,返回流量f
for (int &v = iter[u]; v < G[u].size(); v++)
//这里用iter数组表示每个点目前的弧,这是为了防止在一次寻找增广路的时候,对一些边多次遍历
//在每次找增广路的时候,数组要清空
{
edge &now = e[G[u][v]];
if (now.c - now.f > && level[u] < level[now.v])
//now.c - now.f > 0表示这条路还未满
//level[u] < level[now.v]表示这条路是最短路,一定到达下一层,这就是Dinic算法的思想
{
int d = dfs(now.v, t, min(f, now.c - now.f));
if (d > ) {
to[now.u] = now.v;
tag[now.v] = ;
now.f += d;//正向边流量加d
e[G[u][v] ^ ].f -= d;
//反向边减d,此处在存储边的时候两条反向边可以通过^操作直接找到
return d;
}
}
}
return ;
}
int Maxflow(int s, int t) {
int flow = ;
for (;;) {
BFS(s);
if (level[t] < )return flow;//残余网络中到达不了t,增广路不存在
memset(iter, , sizeof(iter));//清空当前弧数组
int f;//记录增广路的可增加的流量
while ((f = dfs(s, t, inf)) > ) {
flow += f;
}
}
return flow;
} int main()
{
int n, m;
scanf("%d%d", &n, &m);
int s = , t = n + n + ;
for(int i=;i<=m;i++)
{
int x, y;
scanf("%d%d", &x, &y);
addedge(x, y + n, );
}
for(int i=;i<=n;i++)
{
addedge(s, i, );
addedge(i + n, t, );
}
memset(to, -, sizeof(to));
memset(tag, , sizeof(tag));
int ans = Maxflow(s, t);
ans = n - ans;
for(int i=;i<=n;i++)
{
if (tag[i + n]) continue;
int x = i;
while()
{
printf("%d ", x);
if (to[x] == -) break;
x = to[x] - n;
}
printf("\n");
}
printf("%d\n", ans);
return ;
}

P2764 最小路径覆盖问题 网络流重温的更多相关文章

  1. P2764 最小路径覆盖问题(网络流24题之一)

    题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开 ...

  2. 洛谷-p2764(最小路径覆盖)(网络流24题)

    #include<iostream> #include<algorithm> #include<queue> #include<cstring> #in ...

  3. 洛谷 P2764 最小路径覆盖问题 解题报告

    P2764 最小路径覆盖问题 问题描述: 给定有向图\(G=(V,E)\).设\(P\) 是\(G\) 的一个简单路(顶点不相交)的集合.如果\(V\) 中每个顶点恰好在\(P\) 的一条路上,则称\ ...

  4. Luogu 2764 最小路径覆盖问题 / Libre 6002 「网络流 24 题」最小路径覆盖 (网络流,最大流)

    Luogu 2764 最小路径覆盖问题 / Libre 6002 「网络流 24 题」最小路径覆盖 (网络流,最大流) Description 给定有向图G=(V,E).设P是G的一个简单路(顶点不相 ...

  5. Luogu P2764 最小路径覆盖问题(二分图匹配)

    P2764 最小路径覆盖问题 题面 题目描述 «问题描述: 给定有向图 \(G=(V,E)\) .设 \(P\) 是 \(G\) 的一个简单路(顶点不相交)的集合.如果 \(V\) 中每个顶点恰好在 ...

  6. 网络流二十四题之P2764 最小路径覆盖问题

    题目描述 给定有向图 G=(V,E)G=(V,E) .设 PP 是 GG 的一个简单路(顶点不相交)的集合.如果 VV 中每个定点恰好在PP的一条路上,则称 PP 是 GG 的一个路径覆盖.PP中路径 ...

  7. 洛谷 P2764 最小路径覆盖问题【最大流+拆点+路径输出】

    题目链接:https://www.luogu.org/problemnew/show/P2764 题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V ...

  8. luogu P2764 最小路径覆盖问题

    题目描述 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开始,长度也是任 ...

  9. P2764 最小路径覆盖问题

    题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开 ...

随机推荐

  1. [编译] 7、在Linux下搭建安卓APP的开发烧写环境(makefile版-gradle版)—— 在Linux上用命令行+VIM开发安卓APP

    April 18, 2020 6:54 AM - BEAUTIFULZZZZ 目录 0 前言 1 gradle 安装配置 1.1 卸载系统默认装的gradle 1.2 下载对应版本的二进制文件 1.3 ...

  2. 基于my-DAQ的温室迷你温室设计

    这是一个小项目,采用NI的my-DAQ做数据采集,需要采集的数据有温度(LM35),气体(MQ2),需要控制的设备有风扇.加热棒,另外还有光照亮度调节. 一.数据采集 1.LM35 LM35是模拟输出 ...

  3. 极简教程!教你快速将K3s与Cloud Controller集成

    作者: Dawid Ziolkowski,云原生工程师 原文链接: https://itnext.io/how-to-integrate-k3s-with-the-cloud-controller-3 ...

  4. 基于 Redis 的订阅与发布

    Github 仓库 demo-redis-subscribe 创建项目 $ composer create hyperf/biz-skeleton demo-redis-subscribe dev-m ...

  5. Sprint 2 : ios图形界面设计与代码整合

    这周我们主要focus在personal photo experience 项目的ios图形界面设计与代码整合工作上. 工作进度: 1. 图形界面设计方面:兆阳和敏龙基本已经将ios手机客户端的雏形界 ...

  6. GNU的make命令、makefile编写

    makefile简介 makefile可实现工程的自动化编译,只需一个make命令即可一键完成.makefile定义了一些规则,指定哪些文件需要先编译.后编译.重新编译等. 一般的C或者C++程序,都 ...

  7. windows编译动态链接库,dll+lib的形式

    之前一直在linux上做开发,没怎么关注过windows上如何编译动态链接库.不过一直存疑,为什么windows上的动态链接库是.dll配合.lib使用的,这个又是怎么生成的呢,通过一段时间的查资料和 ...

  8. JS 的基础概念

    本篇文章主要讲述js的基础知识! 首先,我们要明白什么是JS,JS就是 javascript 的简称,是一种轻量级,弱类型的脚本语言,已经被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能, ...

  9. 吊打面试官系列:Redis 性能优化的 13 条军规大全

    1.缩短键值对的存储长度 键值对的长度是和性能成反比的,比如我们来做一组写入数据的性能测试,执行结果如下: 从以上数据可以看出,在 key 不变的情况下,value 值越大操作效率越慢,因为 Redi ...

  10. git基本设置——git工具篇

    1.设置邮箱和用户名 /*解释: --global 选项代表对 Git 进行全局设置.*/ $ git config --global user.name "Your Name" ...