只想感叹构图太厉害了
把每个筐拆成三个点连成三元环,对于每个限制条件,把球代表的点连三条边到筐的三个点,匹配数减去$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);
}
}