Luogu P2764 最小路径覆盖问题(二分图匹配)
题面
题目描述
«问题描述:
给定有向图 。设 是 的一个简单路(顶点不相交)的集合。如果 中每个顶点恰好在 的一条路上,则称 是 的一个路径覆盖。 中路径可以从 的任何一个顶点开始,长度也是任意的,特别地,可以为 。 的最小路径覆盖是 的所含路径条数最少的路径覆盖。设计一个有效算法求一个有向无环图 的最小路径覆盖。提示:设 ,构造网络 如下:
«编程任务:
对于给定的给定有向无环图 ,编程找出 的一个最小路径覆盖。
输入输出格式
输入格式:
输入文件第 行有 个正整数 和 。 是给定有向无环图 的顶点数, 是 的边数。接下来的 行,每行有 个正整数 和 ,表示一条有向边 。
输出格式:
从第 行开始,每行输出一条路径。文件的最后一行是最少路径数。
输入输出样例
输入样例:
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
说明
思路
“最小路径覆盖大家都会吧?” --老师
“会啊。” --huyufeifei
“嗯。” --logeadd
国庆集训正式开始啦!今天早上讲的是图论。老师打开的 标题为 NOI中的图论算法
,身为蒟蒻的我还以为老师少打了一个 p
,结果讲了一上午的黑题...我的任务计划变成了上午讲过的题:
讲到P2304 [NOI2015]小园丁与老司机的时候老师问了上面的那个问题,大家都说会,深深感受到了周围都是神仙的恐惧...我就现在把这题写了。
说下思路:首先最小路径覆盖的最坏答案就是 ,也就是每个节点都不得不用一条路径去覆盖它。而很容易发现,有边相连的两个点可以用同一路径来覆盖,那么我们就可以把这样的两个点缩到同一条路径之中。能把更多的点缩起来,就能用最少的边达成目的。设我们能缩 组点,那么最终答案就是 。
因为每个点只能缩一次,所以就可以用二分图最大匹配的方法来转换问题,匈牙利算法和最大流都是可行的,在这里我使用的是码量较小的匈牙利。
AC代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN=160;
const int MAXM=6010;
int n,m,ans,match[MAXN],inv[MAXN];
int cnt,top[MAXN],to[MAXM],nex[MAXM];
int js,edge[MAXN];
bool vis[MAXN];
int read()
{
int re=0;
char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
return re;
}
bool dfs(int now)
{
for(int i=top[now];i;i=nex[i])
{
if(!vis[to[i]])
{
vis[to[i]]=true;
if(!match[to[i]]||dfs(match[to[i]]))
{
match[to[i]]=now;
inv[now]=to[i];
return true;
}
}
}
return false;
}
void fd(int now)
{
vis[now]=true,edge[js++]=now;
if(inv[now]&&!vis[inv[now]]) fd(inv[now]);
if(match[now]&&!vis[match[now]]) fd(match[now]);
}
int main()
{
ans=n=read(),m=read();
while(m--)
{
int x=read(),y=read();
to[++cnt]=y,nex[cnt]=top[x],top[x]=cnt;
}
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof vis);
if(dfs(i)) ans--;
}
for(int i=1;i<=n;i++)
{
js=0;
if(!vis[i])
{
fd(i);
sort(edge,edge+js);
for(int j=0;j<js;j++) printf("%d ",edge[j]);
puts("");
}
}
printf("%d",ans);
return 0;
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· 开发的设计和重构,为开发效率服务
· 从零开始开发一个 MCP Server!
· Ai满嘴顺口溜,想考研?浪费我几个小时
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想