版权声明:欢迎转载(请附带原链接)ヾ(๑╹◡╹)ノ" https://blog.csdn.net/corsica6/article/details/84403112
题解
结论: 的最小路径覆盖数等于点数-最大二分图匹配数。
一种证明方法:
初始每个点自身是一条路径(一共
条),两个点匹配上代表两条不相交的路径连起来了,则路径数-1,每个点入度
(最多被匹配一次)。
将每个点拆成
(分别表示入度出度),边
在二分图中为
,则答案为
-二分图最大匹配数。
二分图最大匹配写起来比最大流简洁得多啊。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=155;
typedef long long ll;
int n,m,g[N][N],bel[N],ans;
int vs[N],f[N],tim,id[N];
vector<int>a[N];
int getfa(int x){return x==f[x]?x:f[x]=getfa(f[x]);}
bool dfs(int x)
{
for(int i=1;i<=n;++i)
if(g[x][i] && (vs[i]!=tim)){
vs[i]=tim;
if((!bel[i])||dfs(bel[i])){
bel[i]=x;return true;
}
}
return false;
}
int main(){
int i,j,x,y;
scanf("%d%d",&n,&m);
for(i=1;i<=m;++i){
scanf("%d%d",&x,&y);
g[x][y]=1;
}
for(i=1;i<=n;++i){tim++;f[i]=i;dfs(i);}
for(i=1;i<=n;++i) if(bel[i]) {
x=getfa(i);y=getfa(bel[i]);f[x]=y;
}
for(tim++,i=1;i<=n;++i){
if(!id[getfa(i)]) id[getfa(i)]=++ans;
a[id[getfa(i)]].push_back(i);
}
for(i=1;i<=ans;++i){
x=a[i].size();
for(j=0;j<x;++j) printf("%d ",a[i][j]);
puts("");
}
printf("%d",ans);
return 0;
}