問題の意味
そこ\(N- \)ボール、\(M \)バスケット、\(E \)条件\((U、V)\) 、ショー球状\(U \)バスケットに入れることができます\(V \)内部。
各ボールがバスケットに配置する必要があり、各バスケットはまで置くことができます\(3 \)数は超えていない場合はボール、バスケットボール(1 \)\、バスケットがあったと主張し、フル半分の。
多くのバスケットは半分、およびプログラムの出力に作ることができるか尋ねてください。
バスケットに各ボールするようにデータを確実にするソリューションが存在しなければなりません。
思考
マッチングの問題。
入れバスケットだけで3個のボールを入れて見バスケットを。
バスケット場合は半分がいっぱい、それは、少なくともでなければなりません\(2 \)バスケットを空にします。
2つの空のバスケットのために、彼らは彼らが今一致させ、その後、他のボールを一致させることができません。
したがって、点のようなボールの各々は、各バスケットのための3つの点として、シーク最大整合グラフは、一般的に良い、花とボードのセット。(花の研究ノートと)
各ボールがバスケットに入れなければならないので、それほど増大経路を見つけるための出発点として、第1のボール:音符。
コード
#include<bits/stdc++.h>
using namespace std;
const int __=600+7;
const int ___=200000+7; // 记得算好总共有多少条边
int T,n,m,e,col[__],pre[__],mat[__],fa[__],fp[__],sym,ans,bel[__],tota;
int lst[__],nxt[___],to[___],tot;
queue<int> q;
void add(int x,int y){ nxt[++tot]=lst[x]; to[tot]=y; lst[x]=tot; }
int find(int x){ return fa[x]==x ?x :fa[x]=find(fa[x]); }
int Lca(int x,int y){
sym++;
while(1){
if(x){
x=find(x);
if(fp[x]==sym) return x;
else{ fp[x]=sym; x=pre[mat[x]]; }
}
swap(x,y);
}
return 0;
}
void con(int x,int y,int lca){
while(find(x)!=lca){
pre[x]=y; fa[x]=lca;
y=mat[x];
col[y]=1; q.push(y);
mat[y]=x; fa[y]=lca;
x=pre[y];
}
}
bool aug(int x){
for(int i=1;i<=tota;i++){ col[i]=pre[i]=0; fa[i]=i; }
while(!q.empty()) q.pop();
q.push(x); col[x]=1;
while(!q.empty()){
int u=q.front(); q.pop();
for(int i=lst[u];i;i=nxt[i]){
int v=to[i];
if(find(u)==find(v)||col[v]==2) continue;
if(!col[v]){
pre[v]=u; col[v]=2;
if(!mat[v]){
while(v){
int t=mat[pre[v]];
mat[v]=pre[v];
mat[pre[v]]=v;
v=t;
}
return 1;
}
else{ col[mat[v]]=1; q.push(mat[v]); }
}
else{
int lca=Lca(u,v);
con(u,v,lca); con(v,u,lca);
}
}
}
return 0;
}
int main(){
//freopen("x.in","r",stdin);
cin>>T;
while(T--){
scanf("%d%d%d",&n,&m,&e);
int x,y; tot=ans=0; tota=n+3*m;
memset(lst,0,sizeof(lst));
memset(mat,0,sizeof(mat));
for(int i=1;i<=e;i++){
scanf("%d%d",&x,&y);
add(x,y+n); add(y+n,x);
add(x,y+n+m); add(y+n+m,x);
add(x,y+n+m+m); add(y+n+m+m,x);
}
for(int i=1;i<=m;i++){
add(i+n,i+n+m); add(i+n+m,i+n);
add(i+n,i+n+m+m); add(i+n+m+m,i+n);
add(i+n+m,i+n+m+m); add(i+n+m+m,i+n+m);
bel[i+n]=bel[i+n+m]=bel[i+n+m+m]=i;
}
for(int i=1;i<=tota;i++){
if(!mat[i]) ans+=aug(i);
}
printf("%d\n",ans-n);
for(int i=1;i<=n;i++) printf("%d ",bel[mat[i]]); putchar('\n');
}
return 0;
}