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. AJ学IOS 之CoreLocation地理编码小Demo输入城市得到经纬度

    AJ分享,必须精品 一:效果 输入地名,可以得到相应的经纬度,知识为了学习写的小Demo 二:实现步骤 一 :首先获取用户输入的位置. 二 :创建地理编码对象. 三 :利用地理编码对象编码,根据传入的 ...

  2. IdentityServer4 QuckStart 授权与自定义Claims

    最近在折腾IdentityServer4,为了简单,直接使用了官方给的QuickStart示例项目作为基础进行搭建.有一说一,为了保护一个API,感觉花费的时间比写一个API还要多. 本文基于ASP. ...

  3. day7作业

    # day7作业 # 1. 使用while循环输出1 2 3 4 5 6 8 9 10 count = 1 while count < 11: if count == 7: count += 1 ...

  4. SpringBoot系列(八)分分钟学会Springboot多种解决跨域方式

    SpringBoot系列(八) 分分钟学会SpringBoot多种跨域解决方式 往期推荐 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 s ...

  5. mybatis一级缓存让我憔悴

    Mybatis对缓存提供支持,是默认开启一级缓存. 来一段代码,这边使用的是mybatis-plus框架,通过构建 QueryWrapper 查询类来实现的. @Transactional publi ...

  6. radio取值

    假设代码如下: 1) <input type="radio"   name="radio"   id="radio1"  checke ...

  7. 虚拟机体验NAS私人云全揭秘:序言——虚拟机体验NAS私人云缘由

    "世界在新冠肺炎疫情后将永远改变",对于2020春天在全球蔓延的新冠肺炎疫情,美国前国务卿基辛格做了这样的评价.确实,也改变了我们.春节期间,本着少添乱的原则,响应国家号召,自我隔 ...

  8. bytectf2019 boring_code的知识学习&&无参数函数执行&&上海市大学生CTF_boring_code+

    参赛感悟 第三次还是第二次参加这种CTF大赛了,感悟和学习也是蛮多的,越发感觉跟大佬的差距明显,但是还是要努力啊,都大三了,也希望出点成绩.比赛中一道WEB都没做出来,唯一有点思路的只有EZCMS,通 ...

  9. 牛顿迭代法的理解与应用( x 的平方根)

    题目来源与LeetCode算法题中的第69题,具体内容如下(点击查看原题): 实现 int sqrt(int x) 函数. 计算并返回 x 的平方根,其中 x 是非负整数. 由于返回类型是整数,结果只 ...

  10. go的 三个点 ...

    这三个点,比较任性,可前可后,可攻可守... 举2个栗子: 1.func sub(arg ...int) (total int){} 2.argsArr = apend(argsArr[:3], ar ...