洛谷 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 的任何一个顶点开 ...
随机推荐
- POJ 2728(最优比率生成树+01规划)
Dese ...
- 洛谷P2593 [ ZJOI 2006 ] 超级麻将 —— DP
题目:https://www.luogu.org/problemnew/show/P2593 DP的话,考虑到当前这一位只跟前两位有关,所以记录一下这3位的状态就行: 于是一开始记录的第 i 位,i- ...
- 第2章 安装Nodejs 2-2 Nodejs版本常识
- idea UML快捷键
- Ionic学习记录(一):ionic及cordova安装、创建第一个应用、项目结构
目录: 一.ionic的安装 二.创建第一个应用程序 三.浏览器中预览应用 四.项目结构 五.添加页面 一.ionic的安装 使用Ionic创建和开发应用程序主要通过Ionic命令行实用程序(“CLI ...
- 讲究地使用 List
本篇旨意在于讨论List的基本用法,不做全面讲解,仅仅涉及构造函数List.Add.RemoveAt 先看看这几个函数的代码 1.构造函数 static readonly T[] _emptyArra ...
- MySql-Connector for NET 连接驱动选择
尝试在Visual Studio2010, 2012环境下链接Mysql, 为啥不直接在App.config里面写字符串, 当然是可以,但是当你想用EF 的时候,必须要有个数据源, 首先在[服务资源管 ...
- 运用<body>属性,渲染页面效果
新建一个HTML5文件,为<body>标签添加样式,代码如下: 01 <!doctype html> 02 <html> 03 <head> 04 &l ...
- Android 概览屏幕
文章照搬过来的:原文地址https://developer.android.google.cn/guide/components/recents.html 概览屏幕(也称为最新动态屏幕.最近任务列表或 ...
- 从Hive1.0升级到Hive2.0(删除hive1.x中的元数据, 并不是数据迁移)
软件环境: linux系统: CentOS6.7 Hadoop版本: 2.6.5 zookeeper版本: 3.4.8 主机配置: 一共m1, m2, m3这五部机, 每部主机的用户名都为centos ...