传送门
这题还是很妙的
话说,我写带花树还是挺熟练的呀qwq
这题大概就是考虑如何让筐体现出它的价值
首先每个筐拆成三个点,分别代表三个空位
然后对于每个球可以放入框的对应关系,我们连三条边
最后再每个筐的三个点之间互相连边
如下图所示:(图是我拿来的)
这样来个带花树就做出来了
当然最后答案要-n
而且输出方案注意一下
还有边表开够
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#define LL long long
using namespace std;
inline int read(){
int x=0,f=1;char ch=' ';
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
const int N=605,M=5e5;
int tot,cnt,top,sum;
int head[M],to[M],Next[M];
inline void addedge(int x,int y){to[++tot]=y;Next[tot]=head[x];head[x]=tot;}
inline void ins(int x,int y){addedge(x,y);addedge(y,x);}
int f[N],vis[N],pre[N],nxt[N],q[N],s[N];
inline int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
inline int lca(int x,int y){
for(cnt++,x=find(x),y=find(y);;swap(x,y))
if(x){
if(vis[x]==cnt)return x;
vis[x]=cnt;
x=find(pre[nxt[x]]);
}
}
inline void blossom(int x,int y,int flower){
while(find(x)!=flower){
pre[x]=y;
if(s[nxt[x]]==1)s[q[++top]=nxt[x]]=0;
if(f[x]==x)f[x]=flower;
if(f[nxt[x]]==nxt[x])f[nxt[x]]=flower;
y=nxt[x];
x=pre[y];
}
}
inline int match(int st){
for(int i=1;i<=sum;++i)f[i]=i;
memset(s,-1,sizeof(s));
s[q[top=1]=st]=0;int x;
for(int l=1;l<=top;++l)
for(int i=head[x=q[l]];i;i=Next[i]){
int u=to[i];
if(s[u]==-1){
pre[u]=x;
s[u]=1;
if(!nxt[u]){
for(int v=x,lst;v;u=lst,v=pre[u])
lst=nxt[v],nxt[v]=u,nxt[u]=v;
return 1;
}
s[q[++top]=nxt[u]]=0;
}
else if(!s[u] && find(x)!=find(u)){
int flower=lca(x,u);
blossom(u,x,flower);
blossom(x,u,flower);
}
}
return 0;
}
inline int solve(){
int ans=0;
for(int i=1;i<=sum;++i)if(!nxt[i])ans+=match(i);
return ans;
}
int T,n,m,E;
int main(){
T=read();
for(int s=1;s<=T;++s){
n=read();m=read();E=read();
sum=n+m*3;tot=0;cnt=0;
memset(head,0,sizeof(head));
memset(nxt,0,sizeof(nxt));
memset(pre,0,sizeof(pre));
memset(vis,0,sizeof(vis));
for(int i=1;i<=E;++i){
int u=read(),v=read();
ins(u,n+v);
ins(u,n+m+v);
ins(u,n+(m<<1)+v);
}
for(int i=1;i<=m;++i){
ins(n+i,n+m+i);
ins(n+i,n+(m<<1)+i);
ins(n+m+i,n+(m<<1)+i);
}
printf("%d\n",solve()-n);
for(int i=1;i<=n;++i)printf("%d ",(nxt[i]-n-1)%m+1);
}
return 0;
}