图论:带花树算法-一般图最大匹配
一般图匹配就是给一般图像二分图那样做最大匹配
问你最大能匹配多少对,带花树算法的过程这里不再描述
直接上模板
1 //It is made by ljh2000 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 using namespace std; 9 typedef long long LL; 10 const int MAXN = 520; 11 const int MAXM = 250011; 12 const int MAXL = 10011; 13 int n,m,ecnt,first[MAXN],next[MAXM],to[MAXM],father[MAXN],Tim; 14 int dui[MAXL],head,tail,id[MAXN],pre[MAXN],match[MAXN],ans,vis[MAXN]; 15 inline int find(int x){ if(father[x]!=x) father[x]=find(father[x]); return father[x]; } 16 inline int getint(){ 17 int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); 18 if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; 19 } 20 21 inline int lca(int x,int y){ 22 Tim++; 23 while(vis[x]!=Tim) { 24 if(x) { 25 x=find(x); 26 if(vis[x]==Tim) return x; 27 vis[x]=Tim; 28 if(match[x]!=0) x=find(pre[match[x]]); 29 else x=0; 30 } 31 swap(x,y); 32 } 33 return x; 34 } 35 36 inline void change(int x,int y,int k){//把奇环上的点缩成一个点,并且把原来是奇点的点变成偶点,加入队列 37 while(find(x)!=k) { 38 pre[x]=y; int z=match[x]; 39 if(id[z]==1) { id[z]=0; dui[++tail]=z; } 40 if(find(z)==z) father[z]=k; 41 if(find(x)==x) father[x]=k; 42 y=z; x=pre[y]; 43 } 44 } 45 46 inline bool bfs(int ini){ 47 for(int i=1;i<=n;i++) id[i]=-1,father[i]=i; 48 head=tail=0; dui[++tail]=ini; id[ini]=0; int u; 49 while(head<tail) { 50 u=dui[++head]; 51 for(int i=first[u];i;i=next[i]) { 52 int v=to[i]; 53 if(id[v]==-1) { 54 pre[v]=u; id[v]=1; 55 if(!match[v]) { 56 int last,t,now=v; 57 while(now!=0) { 58 t=pre[now]; last=match[t]; 59 match[t]=now; match[now]=t; 60 now=last; 61 } 62 return true; 63 } 64 id[match[v]]=0; dui[++tail]=match[v]; 65 } 66 else if(id[v]==0&&find(u)!=find(v)){ //出现奇环且不是在同一个环中 67 int g=lca(u,v); 68 change(u,v,g); 69 change(v,u,g); 70 } 71 } 72 } 73 return false; 74 } 75 76 inline void work(){ 77 n=getint(); m=getint(); int x,y; 78 for(int i=1;i<=m;i++) { 79 x=getint(); y=getint(); 80 next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; 81 next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x; 82 } 83 for(int i=1;i<=n;i++) if(!match[i]&&bfs(i)) ans++; 84 printf("%d\n",ans); 85 for(int i=1;i<=n;i++) printf("%d ",match[i]); 86 } 87 88 int main() 89 { 90 work(); 91 return 0; 92 }