With trees and flowers

Here, the reference code DY great God of the portal Orz
there is an article about the principle of the blog, but also well written Portal Orz
general with trees and flowers are used for general graph of maximum matching,
the following explain with flowers tree.
Core: find augmenting paths.
To do:
(a search out for each point assignment of colors)
1. augmenting path
assumed to have been a good match for a bunch of points, we do not match from one node s start, BFS generated using the search tree. Whenever find a node u, if u have not been matched, then it can be a successful augmentation; otherwise, we put node u and v together with its partners to the tree, then thrown into the queue continues to search for the v .
2. If the search to the point of being visited (in fact, encountered the ring), then the judgment of the ring.
If the ring is even, i.e., the last starting point and the color point is not the same, that edge is ignored.
If the ring is odd that the last point and the point of departure of the same color, it is reduced in flower (pretty much reduced points).
3. shrink flowers:
first find x, y of LCA-p. (Violence may be)
in the Next [] in the x, y interconnect (form a ring).
And check centrally the operation, we will take into bidirectional each edge (undirected graph).
While the colors are changed to the color of each point of LCA.
4. Continue this process until augmenting path can not find
the code for the code ural1099 title
Link [] represent its mate
G [] FIG memory
Next [] its predecessor in augmenting paths
fa [] and check the focus of the father
type [] on behalf of his color
vis [] does it mean to be visited

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define type Type
#define For(aa,bb,cc) for(int aa=bb;aa<=cc;++aa)
#define ak(aa) memset(aa,0,sizeof(aa))
#define next Next
using namespace std;
const int maxn=1010;
bool G[maxn][maxn],p[maxn];
int link[maxn],fa[maxn],next[maxn],type[maxn];
int n,ans;
queue<int>q;

/*带花树模板*/
struct Blossom_Tree{
    /*并查集维护*/
    int find(int x){
        return x==fa[x]?x:find(fa[x]);
    }
    /*
      将x和LCA连起来,
      将环中的所有颜色改成LCA的颜色
      将环中改为无向图,并改为同一个并查集
    */
    void combine(int x,int y){
        while(x!=y){
            int u=link[x],v=next[u];
            if(find(v)!=y) next[v]=u;
            if(type[u]==1) type[u]=2,q.push(u);
            fa[find(x)]=find(u),fa[find(u)]=find(v);
            x=v;
        }
        return ;
    }

    void contract(int x,int y){
        ak(p);
        int LCA=0;
        /*暴力LCA*/
        for(int i=x;i;i=next[link[i]]) i=find(i),p[i]=1;
        for(int i=y;i;i=next[link[i]]){
            i=find(i);
            if(p[i]){
                LCA=i;
                break;
            }
        }
        /*改双向边,且满足缩花的操作*/
        if(find(x)!=LCA) next[x]=y;
        if(find(y)!=LCA) next[y]=x;
        combine(x,LCA);
        combine(y,LCA);
        return ;
    }

    void bfs(int start){
        while(!q.empty()) q.pop();
        ak(type),ak(next);
        For(i,1,n) fa[i]=i;
        q.push(start),type[start]=1;
        while(!q.empty()){
            int k=q.front();q.pop();
            For(i,1,n){
                if(!G[k][i] || find(k)==find(i) || link[k]==i || type[i]==1) continue;
                /*不联通中,在同一个并查集中,互为配偶,偶环*/
                if(type[i]==2) contract(k,i);//奇环,缩花
                else if(link[i]){//将配偶加入队列
                    next[i]=k;
                    type[i]=1;
                    type[link[i]]=2;
                    q.push(link[i]);
                }else{//成功增广
                    next[i]=k;
                    int pos=i,u=next[pos],v=link[u];
                    while(pos){
                        link[u]=pos,link[pos]=u;
                        pos=v;
                        u=next[pos],v=link[u];
                    }
                    return ;
                }
            }
        }
        return ;
    }
}Tree;

int main(){
    scanf("%d",&n);
    int x,y;
    while(scanf("%d%d",&x,&y)!=EOF){
        G[x][y]=1,G[y][x]=1;
    }
    For(i,1,n){
        if(!link[i]) Tree.bfs(i);
    }
    For(i,1,n){
        if(link[i]) ++ans;
    }
    printf("%d\n",ans);
    For(i,1,n){
        if(link[i] && i<link[i]){
            printf("%d %d\n",i,link[i]);
        }
        link[i]=-1;
    }
    return 0;
}
Published 51 original articles · won praise 6 · views 20000 +

Guess you like

Origin blog.csdn.net/qq_35776579/article/details/54412344