只想感叹构图太厉害了
把每个筐拆成三个点连成三元环,对于每个限制条件,把球代表的点连三条边到筐的三个点,匹配数减去$n$就是答案
下面解释为什么是这样
如果某个筐没放球,那么这个筐的三个点最大匹配数为$1$(三元环选一条边匹配)
如果某个筐放$1$个球,那么最大匹配是$2$(球匹配一个点,未被球匹配的两点互相匹配)
如果某个筐放$2$个球,那么最大匹配是$2$
如果某个筐放$3$个球,那么最大匹配是$3$
因为只有筐是半空时,它的内部会有$1$条匹配边,而这个建模使得每个筐的匹配数减去放球数恰好等于(筐是否半空),所以答案就是匹配数$-n$
应该先从球代表的点开始增广,再从筐代表的点开始增广,这既保证了每个球都被放入,又保证了筐内的匹配数尽可能大
然后就做完了,这个建模的巧妙思路实在是太棒了==
#include<stdio.h> #include<string.h> int h[610],to[200010],nex[200010],q[200010],fa[610],type[610],pre[610],match[610],tm[610],M,n,head,tail; void add(int a,int b){ M++; to[M]=b; nex[M]=h[a]; h[a]=M; } void insert(int x,int y){ add(x,y); add(y,x); } void swap(int&a,int&b){a^=b^=a^=b;} int get(int x){return(fa[x]==x)?x:(fa[x]=get(fa[x]));} int lca(int x,int y){ M++; while(1){ if(x){ x=get(x); if(tm[x]==M)return x; tm[x]=M; x=pre[match[x]]; } swap(x,y); } } void blossom(int x,int y,int p){ while(get(x)!=p){ pre[x]=y; y=match[x]; if(type[y]==2){ type[y]=1; tail++; q[tail]=y; } if(fa[x]==x)fa[x]=p; if(fa[y]==y)fa[y]=p; x=pre[y]; } } int bfs(int x){ int i,now,las; for(i=1;i<=n;i++)fa[i]=i; memset(pre,0,sizeof(pre)); memset(type,0,sizeof(type)); head=tail=1; q[1]=x; type[x]=1; while(head<=tail){ x=q[head]; head++; for(i=h[x];i;i=nex[i]){ if(type[to[i]]==2||get(to[i])==get(x))continue; if(type[to[i]]==0){ type[to[i]]=2; pre[to[i]]=x; if(match[to[i]]==0){ now=to[i]; while(now){ las=match[pre[now]]; match[now]=pre[now]; match[pre[now]]=now; now=las; } return 1; } type[match[to[i]]]=1; tail++; q[tail]=match[to[i]]; }else{ now=lca(x,to[i]); blossom(x,to[i],now); blossom(to[i],x,now); } } } return 0; } int main(){ int T,n,m,e,i,x,y; scanf("%d",&T); while(T--){ memset(h,0,sizeof(h)); memset(match,0,sizeof(match)); memset(tm,0,sizeof(tm)); M=0; scanf("%d%d%d",&n,&m,&e); for(i=1;i<=m;i++){ insert(i*3-2,i*3-1); insert(i*3-1,i*3); insert(i*3,i*3-2); } while(e--){ scanf("%d%d",&x,&y); insert(x+m*3,y*3-2); insert(x+m*3,y*3-1); insert(x+m*3,y*3); } ::n=m*3+n; x=M=0; for(i=::n;i>0;i--){ if(match[i]==0)x+=bfs(i); } printf("%d\n",x-n); for(i=3*m+1;i<=::n;i++)printf("%d ",(match[i]-1)/3+1); } }