一开始还真没想到是一般图匹配这种模型(毕竟才会的带花树)
把每一个盒子拆成3个,每一个可以放置进它的小球分别向这三个点连边,然后这三个点在连成一个三元环,最终答案就是小球数目-匹配数。
由于是一般图,所以套一个带花树就可以了。
NOTICE:寻找增广路时,应该从球先找起,这样子才保证了每个球有地方放置。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define maxn 10010 10 #define llg long long 11 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); 12 llg n,m,sett,father[maxn],pre[maxn],match[maxn],vis[maxn],id[maxn],dl[maxn*10],head,tail,ans,T,totn,e; 13 llg c[1000][1000]; 14 15 vector<llg> a[maxn]; 16 17 llg find(llg x){if (father[x]!=x) father[x]=find(father[x]); return father[x];} 18 19 llg lca(llg x,llg y) 20 { 21 sett++; 22 while (vis[x]!=sett) 23 { 24 if (x) 25 { 26 x=find(x); 27 if (vis[x]==sett) return x; 28 vis[x]=sett; 29 if (match[x]!=0) x=find(pre[match[x]]); 30 else x=0; 31 } 32 33 swap(x,y); 34 } 35 return x; 36 } 37 38 void change(llg x,llg y,llg fa) 39 { 40 llg z; 41 while (find(x)!=fa) 42 { 43 pre[x]=y; z=match[x]; 44 if (id[z]==1) {id[z]=0,dl[++tail]=z;} 45 if (find(z)==z) father[z]=fa; 46 if (find(x)==x) father[x]=fa; 47 y=z; x=pre[y]; 48 } 49 } 50 51 bool bfs(llg p) 52 { 53 llg x,w,v; 54 for (llg i=1;i<=n;i++) id[i]=-1,father[i]=i; 55 head=0,tail=1,dl[1]=p; id[p]=0; 56 do 57 { 58 x=dl[++head],w=a[x].size(); 59 for (llg i=0;i<w;i++) 60 { 61 v=a[x][i]; 62 if (id[v]==-1) 63 { 64 pre[v]=x; 65 id[v]=1; 66 if (!match[v]) 67 { 68 llg last,t,now=v; 69 while (now!=0) 70 { 71 t=pre[now],last=match[t]; 72 match[t]=now; match[now]=t; 73 now=last;// v=t; 74 }//把原lai的匹配和非匹配bian取反 75 return 1; 76 } 77 id[match[v]]=0,dl[++tail]=match[v]; 78 } 79 else 80 if (id[v]==0 && find(v)!=find(x)) 81 { 82 llg dad=lca(x,v); 83 change(x,v,dad); 84 change(v,x,dad); 85 } 86 } 87 }while (head!=tail); 88 return 0; 89 90 } 91 92 void link(llg x,llg y) {a[x].push_back(y),a[y].push_back(x);} 93 94 void init() 95 { 96 for (llg i=1;i<=n;i++) a[i].clear(),vis[i]=match[i]=pre[i]=father[i]=id[i]=dl[i]=0; 97 //for (llg i=1;i<=n;i++) for (llg j=1;j<=n;j++) c[i][j]=c[j][i]=0; 98 scanf("%lld%lld%lld",&n,&m,&e); 99 totn=n; 100 llg x,y; 101 for (llg i=1;i<=e;i++) 102 { 103 scanf("%lld%lld",&x,&y); 104 105 llg po=m*3+x; 106 link(po,y*3-2),link(po,y*3-1),link(po,y*3); 107 //a[x].push_back(y),a[y].push_back(x); 108 } 109 n=n+m*3; 110 for (llg i=1;i<=m;i++) 111 { 112 link(i*3-2,i*3-1),link(i*3-1,i*3),link(i*3,i*3-2); 113 } 114 } 115 116 void oupt() 117 { 118 cout<<ans-totn<<endl; 119 for (llg i=1;i<=totn;i++) 120 { 121 printf("%lld ",(match[3*m+i]-1)/3+1); 122 } 123 printf("\n"); 124 } 125 126 int main() 127 { 128 //yyj("a"); 129 cin>>T; 130 while (T--) 131 { 132 ans=0; 133 init(); 134 for (llg i=n;i>1;i--) 135 if (!match[i] && bfs(i)) ans++; 136 oupt(); 137 } 138 return 0; 139 }
时间: 2024-10-12 23:25:46