uoj#79. 一般圖最大匹配(帶花樹)
阿新 • • 發佈:2019-01-03
帶花樹
不加證明的說一下過程好了:每次從一個未匹配點\(S\)出發bfs,設\(S\)為\(1\)類點,如果當前點\(v\)在本次bfs中未經過,分為以下兩種情況
1.\(v\)是未匹配點,那麼從\(S\)到\(v\)的路徑就是一條增廣路,把這條路徑增廣即可
2.\(v\)是匹配點,那麼把\(v\)設為\(2\)類點,並把\(v\)的匹配點扔進bfs的佇列裡
如果\(v\)已經經過了,且是一個\(1\)類點的話無視,否則如果是一個\(2\)類點,說明找到了一個奇環,把這個奇環縮成一個點(一朵花),並把上面的所有的點都標記為\(2\)號點並扔進bfs佇列裡
然後剩下的看程式碼吧……細節不要問我啊我自己都還沒搞清楚呢QAQ
//minamoto #include<bits/stdc++.h> #define R register #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i) #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) using namespace std; char buf[1<<21],*p1=buf,*p2=buf; inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;} int read(){ R int res,f=1;R char ch; while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1); for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0'); return res*f; } char sr[1<<21],z[20];int C=-1,Z=0; inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} void print(R int x){ if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x; while(z[++Z]=x%10+48,x/=10); while(sr[++C]=z[Z],--Z);sr[++C]='\n'; } const int N=505,M=N*N; struct eg{int v,nx;}e[M];int head[N],tot; inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;} int fa[N],vis[N],Pre[N],match[N],ty[N],q[M]; int h,t,tim,n,m,u,v,res; int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} int LCA(int x,int y){ for(++tim;;swap(x,y))if(x){ x=find(x); if(vis[x]==tim)return x; vis[x]=tim,x=Pre[match[x]]; } } void shrink(int x,int y,int k){ while(find(x)!=k){ Pre[x]=y,y=match[x]; if(ty[y]==2)ty[y]=1,q[++t]=y; if(find(x)==x)fa[x]=k; if(find(y)==y)fa[y]=k; x=Pre[y]; } } bool path(int S){ q[h=t=1]=S; fp(i,1,n)ty[i]=Pre[i]=0,fa[i]=i; while(h<=t){ int u=q[h++]; go(u)if(find(u)!=find(v)&&ty[v]!=2){ if(!ty[v]){ Pre[v]=u,ty[v]=2; if(!match[v]){ int tmp; do{ tmp=v,match[v]=u; v=match[u],match[u]=tmp; u=Pre[v]; }while(u); return true; }q[++t]=match[v],ty[match[v]]=1; }else{ int lca=LCA(u,v); shrink(u,v,lca),shrink(v,u,lca); } } }return false; } int main(){ // freopen("testdata.in","r",stdin); n=read(),m=read(); fp(i,1,m)u=read(),v=read(),add(u,v),add(v,u); fp(i,1,n)res+=(!match[i]&&path(i)); printf("%d\n",res); fp(i,1,n)printf("%d ",match[i]); return 0; }