P2764 [网络流24题]最小路径覆盖问题[最大流]

地址

这题有个转化,求最少的链覆盖→即求最少联通块。

设联通块个数$x$个,选的边数$y$,点数$n$个

那么有 $y=n-x$   即  $x=n-y$

而n是不变的,目标就是在保证每个点入度、出度不大于1的前提下让选的边尽可能地多。

下面网络流建模。

利用二分图匹配建图,左右两点集都包含 n 个点,左点集代表 u 的出度,右点集代表 u 的入度。对于原图中的边 (u,v),从 左边的u点 向 右边的v点 连一条容量为 1 的 边,左点集与超级源点、右点集与超级汇点都分别连一条容量 1 的边,然后从源点做最大流,容量设1保证了我们每个点只流向另外唯一一个点,不会重叠。最大流即为所选边在满足条件下的最多数量。答案就是$n-y$。

spj那个的话就只要找到每一块的起点,也就是入度为0,这个看代码。找到起点就往后查残量为0的边顺着跑到底就行啦。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef pair<int,int> pii;
 5 template<typename T>inline char MIN(T&A,T B){return A<B?A=B,1:0;}
 6 template<typename T>inline char MAX(T&A,T B){return A>B?A=B,1:0;}
 7 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
 8 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
 9 template<typename T>inline T read(T&x){
10     x=0;char c;while(!isdigit(c=getchar()))if(isalpha(c))return x=(int)c;
11     while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();return x;
12 }
13 const int N=150+7,M=10000+7,INF=0x3f3f3f3f;
14 int w[M<<1],v[M<<1],Next[M<<1],Head[N<<1],cur[N<<1],dis[N<<1],tot=1,s,t,n,m;
15 inline void Addedge(int x,int y,int z){
16     v[++tot]=y,Next[tot]=Head[x],Head[x]=tot,w[tot]=z;
17     v[++tot]=x,Next[tot]=Head[y],Head[y]=tot,w[tot]=0;
18 }
19 #define y v[j]
20 inline char bfs(){
21     queue<int> q;q.push(s),memset(dis,0,sizeof dis),dis[s]=1;
22     for(register int i=1;i<=(n<<1)+2;++i)cur[i]=Head[i];
23     while(!q.empty()){
24         int x=q.front();q.pop();
25         for(register int j=Head[x];j;j=Next[j])if(w[j]&&!dis[y]){
26             dis[y]=dis[x]+1,q.push(y);
27             if(y==t)return 1;
28         }
29     }
30     return 0;
31 }
32 int dinic(int x,int flow){
33     if(!flow||x==t)return flow;
34     int rest=flow,k;
35     for(register int j=cur[x];j&&rest;cur[x]=j,j=Next[j])if(w[j]&&dis[y]==dis[x]+1){
36         if(!(k=dinic(y,_min(rest,w[j]))))dis[y]=0;
37         rest-=k,w[j]-=k,w[j^1]+=k;
38     }
39     return flow-rest;
40 }
41 #undef y
42 int x,y,ans;
43 inline void print(int x){
44     printf("%d ",x);
45     for(register int j=Head[x];j;j=Next[j])if(v[j]<s&&!w[j])print(v[j]-n);
46 }
47
48 int main(){//freopen("tmp.in","r",stdin);freopen("tmp.out","w",stdout);
49     read(n),read(m);s=2*n+1,t=2*n+2;
50     for(register int i=1;i<=n;++i)Addedge(s,i,1);
51     for(register int i=n+1;i<=n*2;++i)Addedge(i,t,1);
52     for(register int i=1;i<=m;++i)read(x),read(y),Addedge(x,y+n,1);
53     while(bfs())ans+=dinic(s,INF); ans=n-ans;
54     for(register int i=n+1;i<s;++i){//  s <==> n*2+1
55         int tmp=0;
56         for(register int j=Head[i];j;j=Next[j])if(v[j]<=n&&w[j]){tmp=1;break;}
57         if(!tmp)print(i-n),puts("");
58     }
59     printf("%d\n",ans);
60     return 0;
61 }

原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/10356972.html

时间: 2024-10-12 03:35:24

P2764 [网络流24题]最小路径覆盖问题[最大流]的相关文章

COGS728. [网络流24题] 最小路径覆盖问题

算法实现题8-3 最小路径覆盖问题(习题8-13) ´问题描述: 给定有向图G=(V,E).设P是G的一个简单路(顶点不相交)的集合.如果V中每个顶点恰好在P的一条路上,则称P是G的一个路径覆盖.P中路径可以从V的任何一个顶点开始,长度也是任意的,特别地,可以为0.G的最小路径覆盖是G的所含路径条数最少的路径覆盖.设计一个有效算法求一个有向无环图G的最小路径覆盖. 提示: 设V={1,2,...  ,n},构造网络G1=(V1,E1)如下: 每条边的容量均为1.求网络G1的(x0,y0)最大流.

[网络流24题] 最小路径覆盖问题

Description 问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开始,长度也是任意的,特别地,可以为0.G 的最小路径覆盖是G 的所含路径条数最少的路径覆盖.设计一个有效算法求一个有向无环图G 的最小路径覆盖. 编程任务: 对于给定的给定有向无环图G,编程找出G的一个最小路径覆盖. Input Format 文件第1 行有2个正整数n和m.n是给定有向

【网络流24题】圆桌聚餐(最大流)

[网络流24题]圆桌聚餐(最大流) 题面 Cogs 题解 这道题很简单 首先每个单位的人数限制 直接从源点向单位连边,容量为人数 同样的, 每个桌子向汇点连边,容量为可以坐的人数 因为每个桌子只能够做一个该单位的人 所以,每个单位向桌子连边,容量为1 然后跑一边最大流求方案就行了 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath&

POWOJ 1739: 魔术球问题 DAG最小路径覆盖转最大流

1739: 魔术球问题 题意: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在n根柱子上最多能放多少个球.对于给定的n,计算在n根柱子上最多能放多少个球. tags: 对大佬来说应该是很素的一道题,但某还是花了好多时间才做出来.. 一开始连建图都有点懵,然后最小路径还是新概念,最大匹配也不太懂,最大流倒是会一点. 然后要打印答案,也不

【Codevs1237&amp;网络流24题餐巾计划】(费用流)

题意:一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同. 假设第 i 天需要 ri块餐巾(i=1,2,-,N).餐厅可以购买新的餐巾,每块餐巾的费用为 p 分: 或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分: 或者送到慢洗部,洗一块需 n 天(n>m),其费用为 s<f 分.每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗. 但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量.试设计一个算法为餐厅合理地安排好 N 天

网络流24题小结

网络流24题 前言 网络流的实战应用篇太难做了,因此先完善这一部分 ## 第一题:飞行员配对方案 \(BSOJ2542\)--二分图 最优匹配 题意 两国飞行员\(x\)集合\(y\)集合,\(x\)飞行员可以配对特定的\(y\)集合的飞行员(可无),求一对一配对最大数 Solution 二分图最大匹配裸题,最大流实现 建图:(设\(i\in x\)而\(i'\in y\)) \((S,i,1)~(i',T,1)\) 对\((i,j')\)可匹配\((i,j',1)\) Code 略 ## 第二

LiberOJ #6002. 「网络流 24 题」最小路径覆盖

#6002. 「网络流 24 题」最小路径覆盖 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 给定有向图 G=(V,E) G = (V, E)G=(V,E).设 P PP 是 G GG 的一个简单路(顶点不相交)的集合.如果 V VV 中每个顶点恰好在 P PP 的一条路上,则称 P PP 是 G GG 的一个路径覆盖.P PP 中路径可以从 V VV 的任何一个顶点开始,

LiberOJ 6003. 「网络流 24 题」魔术球 贪心或者最小路径覆盖

6003. 「网络流 24 题」魔术球 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 假设有 n nn 根柱子,现要按下述规则在这 n nn 根柱子中依次放入编号为 1,2,3,4,? 1, 2, 3, 4, \cdots1,2,3,4,? 的球. 每次只能在某根柱子的最上面放球. 在同一根柱子中,任何 2 22 个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在 

[loj #6003]「网络流 24 题」魔术球 二分图最小路径覆盖,网络流

#6003. 「网络流 24 题」魔术球 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 假设有 n nn 根柱子,现要按下述规则在这 n nn 根柱子中依次放入编号为 1,2,3,4,? 1, 2, 3, 4, \cdots1,2,3,4,? 的球. 每次只能在某根柱子的最上面放球. 在同一根柱子中,任何 2 22 个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在