【網路流24題】最小路徑覆蓋問題-二分圖匹配/最大流
阿新 • • 發佈:2018-11-26
題解
結論: 的最小路徑覆蓋數等於點數-最大二分圖匹配數。
一種證明方法:
初始每個點自身是一條路徑(一共
條),兩個點匹配上代表兩條不相交的路徑連起來了,則路徑數-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;
}