Explanation:
First of all, all the balls have to be put into the barrel, so each ball is connected to the feasible barrel
A bucket can hold up to three balls. Consider splitting a bucket into three points
Now the maximum number of half empty barrels is required. If only one point of a barrel matches, then cnt++
But it's possible that there are two points that could be split open and matched to the same bucket, resulting in a smaller answer
There is an ingenious method of drawing, which can separate the open points as much as possible
Three points and two sides of a bucket
In this way, in the case of finding the maximum match, the maximum number of matches placed together is 3, while the maximum number of matches separated is 4
It can solve the problem of maximizing the number of half empty barrels
As shown in the figure: (red is the matching edge)
However, the graph built in this way is not a bipartite graph, but a general graph
So we need to solve the maximum matching problem of general graphs
Tree with flowersIf a general graph has odd rings, it must not be a bipartite graph
If there is such a odd ring in a graph, it may contribute five matching edges
But its interior will only contribute 2 matching edges at most
At most, only one outer point can match the points in the odd ring
So we can consider reducing the odd ring to a point to find the path of augmentation
But after shrinking the points, there are only 1 + 2 matches in the graph that can match 5 edges
All of us can't shrink directly. When dfs reaches this point, we need to expand the shrinking point (flowering)
In this way, we can find the way to increase
The following paragraph is quoted from: https://www.cnblogs.com/owenyu/p/6858508.html
Paste template:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 305 #define M 500005 int fir[N],to[M],nxt[M],cnt; void adde(int a,int b) { to[++cnt]=b;nxt[cnt]=fir[a];fir[a]=cnt; to[++cnt]=a;nxt[cnt]=fir[b];fir[b]=cnt; } namespace FT{ int sz; int fa[N],pre[N],mat[N],vis[N]; int q[N],he,ta; int tim[N],tm; int find(int x) int lca(int x,int y){ for(tm++;;swap(x,y))if(x){ x=find(x); if(tim[x]==tm)return x; tim[x]=tm;x=pre[mat[x]]; } } void bls(int x,int y,int p){ while(find(x)!=p){ pre[x]=y;y=mat[x]; if(vis[y]==2)vis[y]=1,q[++ta]=y; if(find(x)==x)fa[x]=p; if(find(y)==y)fa[y]=p; x=pre[y]; } } bool bfs(int s){ for(int i=1;i<=sz;i++)fa[i]=i; memset(vis,0,sizeof(vis));memset(pre,0,sizeof(pre)); he=1;ta=0;q[++ta]=s;vis[s]=1; while(he<=ta){ int u=q[he++]; for(int v,p=fir[u];p;p=nxt[p]){ if(vis[v=to[p]]==2||find(u)==find(v))continue; if(!vis[v]){ vis[v]=2;pre[v]=u; if(!mat[v]){ for(int tmp;v;v=tmp){ tmp=mat[u=pre[v]]; mat[v]=u;mat[u]=v; } return 1; } vis[mat[v]]=1;q[++ta]=mat[v]; } else{ int x=lca(u,v); bls(u,v,x);bls(v,u,x); } } } return 0; } }//----FT----
Code:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 605 #define M 500005 int fir[N],to[M],nxt[M],cnt; void adde(int a,int b) { to[++cnt]=b;nxt[cnt]=fir[a];fir[a]=cnt; to[++cnt]=a;nxt[cnt]=fir[b];fir[b]=cnt; } int fa[N],pre[N],match[N],vis[N],q[N],he,ta; int find(int x) int sz,tim[N],tm; int lca(int x,int y) { for(tm++;;swap(x,y))if(x){ x=find(x); if(tim[x]==tm)return x; else tim[x]=tm,x=pre[match[x]]; } } void bls(int x,int y,int p) { while(find(x)!=p){ pre[x]=y;y=match[x]; if(vis[y]==2)vis[y]=1,q[++ta]=y; if(find(x)==x)fa[x]=p; if(find(y)==y)fa[y]=p; x=pre[y]; } } bool bfs(int s) { for(int i=1;i<=sz;i++)fa[i]=i; memset(vis,0,sizeof(vis));memset(pre,0,sizeof(pre)); he=1;ta=0;q[++ta]=s;vis[s]=1; while(he<=ta){ int u=q[he];he++; for(int v,p=fir[u];p;p=nxt[p]){ if(vis[v=to[p]]==2||find(v)==find(u))continue; if(!vis[v]){ vis[v]=2;pre[v]=u; if(!match[v]){ for(int tmp;v;v=tmp){ tmp=match[u=pre[v]]; match[v]=u,match[u]=v; } return 1; } vis[match[v]]=1;q[++ta]=match[v]; } else{ int x=lca(u,v); bls(u,v,x); bls(v,u,x); } } } return 0; } int main() { int T,n,m,E,i,u,v; scanf("%d",&T); while(T--){ memset(fir,0,sizeof(fir));cnt=0; memset(match,0,sizeof(match)); scanf("%d%d%d",&n,&m,&E); sz=n+3*m; for(i=1;i<=E;i++){ scanf("%d%d",&u,&v); adde(u,n+v); adde(u,n+m+v); adde(u,n+2*m+v); } for(i=1;i<=m;i++){ adde(n+i,n+m+i); adde(n+m+i,n+2*m+i); adde(n+i,n+2*m+i); } int ans=0; for(i=1;i<=sz;i++) if(!match[i])ans+=bfs(i); printf("%d\n",ans-n); printf("%d",(match[1]-n-1)%m+1); for(i=2;i<=n;i++) printf(" %d",(match[i]-n-1)%m+1); printf("\n"); } }