洛谷 P2764 LibreOJ 6002 最小路径覆盖问题
题目描述
«问题描述:
给定有向图G=(V,E)。设P 是G 的一个简单路(顶点不相交)的集合。如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖。P 中路径可以从V 的任何一个顶点开始,长度也是任意的,特别地,可以为0。G 的最小路径覆盖是G 的所含路径条数最少的路径覆盖。设计一个有效算法求一个有向无环图G 的最小路径覆盖。提示:设V={1,2,.... ,n},构造网络G1=(V1,E1)如下:
每条边的容量均为1。求网络G1的( 0 x , 0 y )最大流。
«编程任务:
对于给定的给定有向无环图G,编程找出G的一个最小路径覆盖。
输入输出格式
输入格式:
件第1 行有2个正整数n和m。n是给定有向无环图G 的顶点数,m是G 的边数。接下来的m行,每行有2 个正整数i和j,表示一条有向边(i,j)。
输出格式:
从第1 行开始,每行输出一条路径。文件的最后一行是最少路径数。
输入输出样例
11 12
1 2
1 3
1 4
2 5
3 6
4 7
5 8
6 9
7 10
8 11
9 11
10 11
1 4 7 10 11
2 5 8
3 6 9
3
说明
1<=n<=150,1<=m<=6000
吐槽
这题洛谷居然没有SPJ,大家来这里交吧。要在洛谷上AC就必须像造数据的人那样——用链式前向星反着加边,然后跑dinic。我的匈牙利明明能得出一个最优解,洛谷就是给我爆零,大坏蛋。下面的代码能出解不能在洛谷AC,大家别想复制了。因为一些事,心情不爽,我也不太想在洛谷上交dinic了,抄了个题解混一波通过数。
解题思路
裸题。u到v有连边,那么就在二分图里把男u号与女v号牵线,然后跑二分图最大匹配,得到匹配数k,答案最后那行就是$n-k$了。至于前面输出路径,直接顺着二分图走即可,我感觉我的这部分代码挺好懂的(逃)
我的源代码
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; int n,m;
struct men{
int w;//对象
vector<int> lover;
}man[];
int woman[]={};
inline void add(int u,int v)
{
man[u].lover.push_back(v);
} bool vis[];
bool dfs(int u)
{
int sz=man[u].lover.size();
for(int i=;i<sz;i++)
{
int v=man[u].lover[i];
if(vis[v])continue;
vis[v]=;
if(!woman[v]||dfs(woman[v]))
{
woman[v]=u;
man[u].w=v;
return ;
}
}
return ;
}
void print(int i)
{
if(i==||vis[i])
{
printf("\n");
return;
}
vis[i]=;
printf("%d ",i);
print(man[i].w);
}
int main()
{
scanf("%d%d",&n,&m);
memset(man,,sizeof(man));
for(int i=,u,v;i<=m;i++)
scanf("%d%d",&u,&v),add(u,v);
int ans=;
for(int i=;i<=n;i++) reverse(man[i].lover.begin(),man[i].lover.end());
for(int i=;i<=n;i++)
{
memset(vis,,sizeof(vis));
if(dfs(i))ans++;
}
memset(vis,,sizeof(vis));
for(int i=;i<=n;i++)
{
if(!vis[i]) print(i);
}
printf("%d\n",n-ans);
return ;
}
洛谷题解代码
#include <stdio.h>
#include <cstring>
#include <queue>
#define maxn 20000
#define fill(x,y) memset(x,y,sizeof(x))
#define min(x,y) x<y?x:y
#define INF 0x7f7f7f7f
using namespace std;
struct edge{int y,w,rev,next;}e[maxn];
int ls[maxn],n,m,maxE=,vis[maxn],state[maxn];
int add(int x,int y,int w)//将边加入
{
e[++maxE]=(edge){y,w,maxE+,ls[x]};
ls[x]=maxE;
e[++maxE]=(edge){x,,maxE-,ls[y]};
ls[y]=maxE;
return ;
}
int bfs(int x)//暴力搜索
{
queue <int> t;
t.push(x);
fill(state,);
state[x]=;
while (!t.empty())
{
int tt=t.front();t.pop();
for (int i=ls[tt];i;i=e[i].next)
{
if (e[i].w>&&state[tt]+<state[e[i].y])
{
state[e[i].y]=state[tt]+;
t.push(e[i].y);
if (e[i].y==n+n+)
return true;
}
}
}
return false;
}
int find(int x,int mn)//dinic
{
if (x==n+n+) return mn;
for (int i=ls[x];i;i=e[i].next)
if (state[x]+==state[e[i].y]&&e[i].w>)
{
int d=find(e[i].y,min(mn,e[i].w));
if (d>)
{
e[i].w-=d;
e[e[i].rev].w+=d;
vis[x]=e[i].y;//记录路径
return d;
}
}
return ;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y+n,);
}
for (int i=;i<=n;i++)//连边
{
add(,i,);
add(n+i,n+n+,);
}
int ans=; while (bfs())
{
int d=find(,INF);//最大流
ans+=d;
} for (int i=;i<=n;i++)
{
if (vis[i]!=)//输出路径
{
int t=i;
do
{
if (t>n) t-=n;
printf("%d ",t);
int x=vis[t];
vis[t]=;
t=x;
}
while (t!=);
printf("\n");
}
}
printf("%d\n",n-ans);//最小路径覆盖=总点数-最大匹配
return ;
}
洛谷 P2764 LibreOJ 6002 最小路径覆盖问题的更多相关文章
- LibreOJ 6002 最小路径覆盖(最大流)
题解:最小路径覆盖=总点数减去最大匹配数,拆点,按照每条边前一个点连源点,后一个点连汇点跑最大流,即可跑出最大匹配数,然后减一减就可以了~ 代码如下: #include<queue> #i ...
- Loj 6002 最小路径覆盖(最大流)
题意: 求不相交的最小路径覆盖 思路: 连边跑二分图,匹配一条边相当于缩了一条边,答案为n-maxflow 如果是求可以相交的最小路径覆盖的话,先用Floyd跑出可达矩阵,然后所有可达的点连边跑二分图 ...
- 【洛谷 P3187】 [HNOI2007]最小矩形覆盖 (二维凸包,旋转卡壳)
题目链接 嗯,毒瘤题. 首先有一个结论,就是最小矩形一定有条边和凸包重合.脑补一下就好了. 然后枚举凸包的边,用旋转卡壳维护上顶点.左端点.右端点就好了. 上顶点用叉积,叉积越大三角形面积越大,对应的 ...
- 洛谷 P2764 最小路径覆盖问题 解题报告
P2764 最小路径覆盖问题 问题描述: 给定有向图\(G=(V,E)\).设\(P\) 是\(G\) 的一个简单路(顶点不相交)的集合.如果\(V\) 中每个顶点恰好在\(P\) 的一条路上,则称\ ...
- 洛谷 P2764 最小路径覆盖问题【最大流+拆点+路径输出】
题目链接:https://www.luogu.org/problemnew/show/P2764 题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V ...
- 洛谷P2764 最小路径覆盖问题
有向无环图的最小路径点覆盖 最小路径覆盖就是给定一张DAG,要求用尽量少的不相交的简单路径,覆盖有向无环图的所有顶点. 有定理:顶点数-路径数=被覆盖的边数. 要理解的话可以从两个方向: 假设DAG已 ...
- 【刷题】洛谷 P2764 最小路径覆盖问题
题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开 ...
- 洛谷P2764 最小路径覆盖问题(最大流)
传送门 先说做法:把原图拆成一个二分图,每一个点被拆成$A_i,B_i$,若原图中存在边$(u,v)$,则连边$(A_u,B_v)$,然后$S$对所有$A$连边,所有$B$对$T$连边,然后跑一个最大 ...
- AC日记——最小路径覆盖问题 洛谷 P2764
题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开 ...
随机推荐
- Android系统Recovery工作原理之使用update.zip升级过程分析(八)---解析并执行升级脚本updater-script【转】
本文转载自:http://blog.csdn.net/mu0206mu/article/details/7465551 Android系统Recovery工作原理之使用update.zip升级过程分 ...
- Android WiFi开发教程(三)——WiFi热点数据传输
在上一篇文章中介绍了WiFi的搜索和连接,如果你还没阅读过,建议先阅读上一篇Android WiFi开发教程(二)——WiFi的搜索和连接.本篇接着简单介绍手机上如何通过WiFi热点进行数据传输. 跟 ...
- MySQL SQL优化教程
转自:https://www.cnblogs.com/duanxz/archive/2013/02/01/2889413.html 一,查询SQL执行效率 通过show status命令了解各种SQL ...
- JDK5.0新特性(静态导入、自动装箱/拆箱、增强for循环、可变参数、枚举、泛形)
JDK5中新增了很多新的java特性,利用这些新语法可以帮助开发人员编写出更加高效.清晰,安全的代码. 这些新特性主要有:1.静态导入2.自动装箱/拆箱3.增强for循环4.可变参数5.枚举6.泛型7 ...
- 七牛php上传下载类,集成官方文档的方法
<?phpuse Qiniu\Auth;use Qiniu\Storage\UploadManager;class qiniu{ public $_accesskey = null; publi ...
- Win10 计算机管理 打不开应急办法
最近Win10重置以后,计算机管理打不开了,经过一番尝试,通过以下命令在cmd下面可以直接打开 compmgmt 或者compmgmt.msc打开 在次特做一个记录,以备急用
- 安卓通过UDP协议传输数据,中文乱码的问题
公司最近需要往智能家居方面发展,需要用到UDP协议传输数据,在网上找到了一些资料,但是发现传输中文的时候有乱码的现象,经过我多番捣鼓,终于解决了这个问题,下面贴上关键代码 客户端: public cl ...
- Java数据的基本类型
整数类型: byte:8位(1个字节) eg:byte x=2,y: 错误实例:byte b:b=b+3: 其中b=b+3是错误的,应该是b=(byte)(b+3)强制转换: short:16位( ...
- MSP430之data type
- VTK初始化New返回Null问题
原文链接:http://www.cppblog.com/mythma/archive/2013/08/02/vtk-6-new-null.html 在使用VTK6.0时候,会遇到X::New()返回为 ...