728. [网络流24题] 最小路径覆盖问题
★★★☆ 输入文件:path3.in
输出文件:path3.out
评测插件
时间限制:1 s 内存限制:128 MB
´问题描述:
提示:
设V={1,2,... ,n},构造网络G1=(V1,E1)如下:
´编程任务:
´数据输入:
´结果输出:
一条路径。文件的最后一行是最少路径数。
输入文件示例
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
输出文件示例
output.txt
1 4 7 10 11 2 5 8 3 6 9 3
讲解:
Coding!
发现自己还是太弱了
这样一道看起来比较简单的二分图最小路径覆盖问题都能出问题 唉
现在我们来讲一下这一道题的易错点
1.最小路径覆盖数是 节点数n - 二分图的最大匹配数
2.这一道题让输出路径 那么这应该怎么办呢?
我想了一个办法是这个样子的
首先我们在累加那个ans的时候枚举节点跑匈牙利算法dfs的时候不是从小往大枚举的吗
也就是说那个hav数组 在正常的情况下是hav[后]=hav[前] 但是 如果是这个样子 我们不好输出路径 因为我比较想去从头(较小的)开始输出
那么我们再来看一个son数组 和hav数组正好是反过来的
同时我们再设一个in数组 来存储入度
所以经过了上面的处理
我们只需要枚举n个点 如果这个点的入度为0 那么我们就从这个点开始 顺着son往后跑 就能打印出该条路径啦
具体内容看代码理解咯(其实还是比较 简单的 我啰嗦了那么多 还是看代码比较清晰一点啦)
鸿篇巨制:
#include<bits/stdc++.h> #define maxn 205 using namespace std; int n,m; int vis[maxn],hav[maxn],tim=0; vector<int> v[maxn]; int in[maxn]; int son[maxn]; bool Dfs(int x) { for(int i=0;i<v[x].size();i++) { int y=v[x][i]; if(vis[y]!=tim) { vis[y]=tim; if(!hav[y]||Dfs(hav[y])) { hav[y]=x; son[x]=y; in[y]++; return true; } } } return false; } bool Printed[maxn]; void Print(int i) { int x=i; while(x!=0) { printf("%d ",x); Printed[x]=true; x=son[x]; } putchar('\n'); } int main() { freopen("path3.in","r",stdin); freopen("path3.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); v[x].push_back(y); } int ans=0; for(int i=1;i<=n;i++) { tim++; ans+=Dfs(i); } for(int i=1;i<=n;i++) if(in[i]==0) Print(i); printf("%d\n",n-ans); return 0; }
点个赞 加个关注再走呗