n − 最 大 匹 配 数 n-最大匹配数 n−最大匹配数
Analysis
如果问题只有前面部分,即求最小路径覆盖数,那我们很好操作(具体解析见文章顶部博客链接)
而现在还需要输出路径
其实也很简单
在做完网络流之后,对于每个点,它走向的下一个点,就是在网络流残图中与它相连且流量为0的边所对应的点,这个很好记录,关键是输出
如果随便找到一个点就不停沿流量为0 的边走下去,那么这条路径很可能不全
大概是这样的:
(红色的边表示流量为0的边)
如果我们一开始找到的是第三个点,那么这条路径我们就只输出了3->4
而实际上为1->2->3->4
问题就在于起点
这也很好处理
标记一下入度即可
具体见代码实现(很好懂)
Code
#include<bits/stdc++.h>
#define in red()
#define re register
using namespace std;
inline int red(){
char ch;int f=1,res=0;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
while(ch>='0'&&ch<='9'){
res=(res<<1)+(res<<3)+(ch^48);
ch=getchar();
}
return f==1?res:-res;
}
const int N=200,M=6009;
int head[N<<1],nxt[M<<2],to[M<<2],cap[M<<2],ecnt=1;
inline void add(int x,int y,int w){
nxt[++ecnt]=head[x];head[x]=ecnt;to[ecnt]=y;cap[ecnt]=w;
nxt[++ecnt]=head[y];head[y]=ecnt;to[ecnt]=x;cap[ecnt]=0;
}
int S,T,n,m;
int lev[N<<1],cur[N<<1];
bool bfs(){
queue<int> q;
for(re int i=S;i<=T;++i) cur[i]=head[i],lev[i]=-1;
q.push(S);lev[S]=0;
while(!q.empty()){
int u=q.front();
q.pop();
for(re int e=head[u];e;e=nxt[e]){
int v=to[e];
if(lev[v]!=-1||cap[e]<=0) continue;
lev[v]=lev[u]+1;
if(v==T) return 1;
q.push(v);
}
}
return 0;
}
int dinic(int u,int flow){
if(u==T) return flow;
int delta=0,res=0;
for(re int &e=cur[u];e;e=nxt[e]){
int v=to[e];
if(lev[v]>lev[u]&&cap[e]){
delta=dinic(v,min(flow-res,cap[e]));
if(delta){
cap[e]-=delta;cap[e^1]+=delta;
res+=delta;if(res==flow) return res;
}
}
}
return res;
}
int go[N],du[N];
inline int idx(int x){
return (x-1)%n+1;
}
void print_path(){
for(re int i=1;i<=n;++i) go[i]=i;
for(re int i=1;i<=n;++i){
for(re int e=head[i];e;e=nxt[e]){
int j=to[e];
if(j!=S&&j!=T&&cap[e]==0){
go[i]=idx(j);
du[idx(j)]++;
}
}
}
for(re int i=1;i<=n;++i)if(!du[i]){
int x=i;
while(x!=go[x]){
printf("%d ",x);
x=go[x];
}
printf("%d\n",x);
}
}
int main(){
n=in;m=in;S=0;T=2*n+1;
for(re int i=1;i<=n;++i) add(0,i,1),add(i+n,T,1);
for(re int i=1;i<=m;++i){
int u=in,v=in;
add(u,n+v,1);
}
int maxflow=0;
while(bfs()) maxflow+=dinic(S,n);
print_path();
printf("%d",n-maxflow);
return 0;
}
/*
6 6
1 2
1 3
1 6
2 3
3 4
3 5
*/