题面
https://www.luogu.org/problem/P2764
题解
原谅当年的我太弱,把$dinic$拼错。
upd:我发现我当年判边在不在最大流上也是假的。应该看$w[i]是否为0$。
upd:应该是有必要补说一下的,一开始,每个点自成一个路径,然后一个合法的匹配就是把两条路径合二为一,路径数$-1$,所以边可以是有向的。并且不能自己和自己连边。
最后的路径数是$n-G.dinic()$
#include<cstdio> #include<iostream> #define ri register int #define N 20000 using namespace std; int n,m; int head[N],cnt=1; int dep[N],que[N],nex[N],pre[N]; int to[7*N],nxt[7*N],wei[7*N],cur[N]; bool inq[N],vis; void add(int u,int v,int w) { ++cnt; nxt[cnt]=head[u]; to[cnt]=v; wei[cnt]=w; head[u]=cnt; } bool bfs() { for (ri i=1;i<=2*n+2;i++) dep[i]=987654321,cur[i]=head[i],inq[i]=0; que[1]=2*n+1; dep[2*n+1]=1; inq[2*n+1]=1; int tail=1,hd=1; while (tail<=hd) { int x=que[tail]; tail++; inq[x]=0; for (ri i=head[x];i;i=nxt[i]) if (dep[x]+1<dep[to[i]] && wei[i]) { dep[to[i]]=dep[x]+1; if (!inq[to[i]]) que[++hd]=to[i],inq[to[i]]=1; } } return dep[2*n+2]<=n; } int dfs(int x,int mi) { if (x==2*n+2) { vis=1; return mi; } int used=0; int rlow; for (ri i=cur[x];i;i=nxt[i]) { cur[x]=i; if (wei[i] && dep[to[i]]==dep[x]+1) { rlow=dfs(to[i],min(mi-used,wei[i])); if (rlow) { if (1<=x && x<=n && n<to[i] && to[i]<=2*n) { nex[x]=to[i]-n; pre[to[i]-n]=x; } used+=rlow; wei[i]-=rlow; wei[i^1]+=rlow; if (used==mi) return used; } } } return used; } void dicnic(){ while (bfs()) { vis=1; while (vis) { vis=0; dfs(2*n+1,0x3f3f3f3f); } } } void print(int x) { printf("%d ",x); if (nex[x]) print(nex[x]); } int main(){ int u,v; scanf("%d %d",&n,&m); for (ri i=1;i<=m;i++) { scanf("%d %d",&u,&v); add(u,n+v,1); add(n+v,u,0); } for (ri i=1;i<=n;i++) add(2*n+1,i,1),add(i,2*n+1,0); for (ri i=n+1;i<=2*n;i++) add(i,2*n+2,1),add(2*n+2,i,0); dicnic(); int ans=0; for (ri i=1;i<=n;i++) if (!pre[i]) print(i),puts(""),ans++; cout<<ans<<endl; }