#include <bits/stdc++.h>
using namespace std;
const int N=1e4+10,inf=0x3f3f3f3f,M=2e6+1;
int n,m;
int tot=1;
int head[N],ver[M],nxt[M],edge[M];
void add(int u,int v,int w=0){
ver[++tot]=v,nxt[tot]=head[u],head[u]=tot,edge[tot]=w;
}
bool v[N];
int matchy[N],matchx[N];
bool dfs(int x){
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(v[y])continue;
v[y]=1;
if(!matchy[y]||dfs(matchy[y])){
matchy[y]=x;
matchx[x]=y;
return true;
}
}
return 0;
}
int main(){
std::ios::sync_with_stdio(0);
cin>>n>>m;
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
add(x,y+n);
}
int ans=0;
for(int i=1;i<=n;i++){
memset(v,0,sizeof v);
if(dfs(i))ans++;
}
for(int i=n+1;i<=2*n;i++){
if(!matchy[i]){
int x=i-n;
cout<<x<<" ";
while(matchx[x]){
x=matchx[x]-n;
cout<<x<<" ";
}
cout<<endl;
}
}
cout<<n-ans;
}
看洛谷题解的代码太长了,自己这个简单些。
拆点,一条路x->y,则连x->y+n
n个点直接匈牙利求最大匹配,n-最大匹配就是最小路径覆盖
如果起点为i,那么i+n的matchy[i]肯定为0
matchx记录匹配的右边点,然后输出就可以了