General graph maximum match - with trees and flowers algorithm study notes

Before always thought the biggest match of general graphs is an NP problem, inadvertently learned that blooms only know the general algorithm graph maximum matching is also polynomial-time algorithm. With online information to learn about a wave of record.

 Recommended blog: https://www.cnblogs.com/BAJimH/p/10569418.html  (this Gangster principle it very clear that the code also resolved)

https://www.cnblogs.com/owenyu/p/6858508.html  (The chiefs put it simpler, the code is good)

 

Read explanation above Gangster should not difficult to understand this algorithm, the chiefs there is a saying very place: in fact, with blooms that Hungary + processing odd ring . why? Because in fact the general graph matching with bipartite graph matching without lies, general graphs there may be the odd ring (bipartite graph certainly did not), while bipartite graph matching classical algorithm Hungary algorithm can not handle odd ring, so special handling odd ring . In fact, we observed an odd length 2k + 1 internal ring of his own form of k match, then the rest will be leaving only a point to seek to match the outside, so from this perspective odd ring can be seen as a point so we can put the odd banding point, when the point of this odd ring to match the extra need to seek out the odd ring expand, shrink finished Tucci ring on it as a bipartite graph matching run. Focus algorithm is how odd ring contraction and expansion odd ring, used here a very clever way: disjoint-set + LCA. Disjoint-set record for each vertex point where the odd ring initially is its own. Shrink ring, we will direct all points on the ring vertex disjoint-set father even to odd ring, and ring stain on the point, and join the queue. Find a new odd ring, then find u, v top ring where the ring is odd (ie lca they ran out in the BFS staggered tree, called the recent public spend ancestor), u will ring to the top of the path and v the top ring path modification off white point dyed black spots, join the queue, the point (or a shrink ring has a top) and the ring on the father disjoint-set point lca. (This passage is a Gangster original, the proposal directly to the chiefs blog to see)

Ashamed that while the konjac is able to see the energy principle, but in fact can not be in-depth understanding of the implementation details of the code, resulting in not looking at the code to write their own, let us put it as a black box code to use it.

 

Topic Exercise:

 UOJ # 79

With bare blooms matching problem, a reference code is big brother. An input point n in FIG m edges, and an output matching the maximum possible maximum matching scheme.

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=505;
 4 const int M=N*N*2;
 5 int n,m,que[M],ql,qr,pre[N],tim=0;
 6 int h[N],tot=0;
 7 int match[N],f[N],tp[N],tic[N];
 8 struct edge {
 9     int v,nxt;
10 } e[M];
11 
12 int find(int x) { return f[x]==x?f[x]:f[x]=find(f[x]); }
13 
14 void add(int u,int v) {
15     e[++tot]=(edge){v,h[u]};
16     h[u]=tot;
17 }
18 
19 int lca(int x,int y) {
20     for (++tim;;swap(x,y)) if (x) {
21         x=find(x);
22         if (tic[x]==tim) return x; else tic[x]=tim,x=pre[match[x]];
23     }
24 }
25 
26 void shrink(int x,int y,int p) {
27     while (find(x)!=p) {
28         pre[x]=y,y=match[x];
29         if (tp[y]==2) tp[y]=1,que[++qr]=y;
30         if (find(x)==x) f[x]=p;
31         if (find(y)==y) f[y]=p;
32         x=pre[y];
33     }
34 }
35 
36 bool aug(int s) {
37     for (int i=1;i<=n;++i) f[i]=i;
38     memset(tp,0,sizeof tp),memset(pre,0,sizeof pre);
39     tp[que[ql=qr=1]=s]=1; // 1: type A ; 2: type B
40     int t=0;
41     while (ql<=qr) {
42         int x=que[ql++];
43         for (int i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v) {
44             if (find(v)==find(x) || tp[v]==2) continue; 
45             if (!tp[v]) {
46                 tp[v]=2,pre[v]=x;
47                 if (!match[v]) {
48                     for (int now=v,last,tmp;now;now=last) {
49                         last=match[tmp=pre[now]];
50                         match[now]=tmp,match[tmp]=now;
51                     }
52                     return true;
53                 } 
54                 tp[match[v]]=1,que[++qr]=match[v];
55             } else if (tp[v]==1) {
56                 int l=lca(x,v);
57                 shrink(x,v,l);
58                 shrink(v,x,l);
59             }
60         }
61     }   
62     return false;
63 }
64 
65 int main()
66 {
67     scanf("%d%d",&n,&m);
68     for (int i=1;i<=m;++i) {
69         int x,y; scanf("%d%d",&x,&y);
70         add(x,y),add(y,x);
71     }
72     int ans=0;
73     for (int i=1;i<=n;++i) ans+=(!match[i] && aug(i));
74     printf("%d\n",ans);
75     for (int i=1;i<=n;++i) printf("%d ",match[i]);
76     puts("");
77     return 0;
78 }
View Code

 estimated 3316

Meaning of the title is given n-dimensional chess board, gives a distance L. Two men take turns to take away pieces on the board, and only want to take the current and the last piece of Manhattan from the other side to take away pieces of the L or less before they can take, both sensible enough to ask whether flac win. This question is at first glance is the game theory, but this is not a fair game, so I do not use knowledge of game theory SG functions, and so resolved. Easy to think of the distance is less than the figure two equal pieces even L side, this picture becomes more blocks Unicom, China Unicom let's consider only a block under what circumstances the upper hand win / win FLAC? Own hand-drawn map found several blocks long as this is not a perfect match for China Unicom, have the upper hand winning strategy (which is also the blogger know in advance This question is resolved with trees and flowers can think of qwq). On the contrary only Unicom block is a perfect match to win only way of escape. So there are multiple blocks Unicom how to do? It is also relatively easy to think, want to win the upper hand to make sure to choose a block Unicom him win, as long as there is at least one non-all perfectly matched Unicom block is to win the upper hand. So we can look with trees and flowers.

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=370;
 4 const int M=N*N*2;
 5 int n,m,x[N],y[N],L,que[M],ql,qr,pre[N],tim=0,scc,id[N],siz[N],num[N];
 6 int h[N],tot=0;
 7 int match[N],f[N],tp[N],tic[N];
 8 struct edge {
 9     int v,nxt;
10 } e[M];
11 
12 int find(int x) { return f[x]==x?f[x]:f[x]=find(f[x]); }
13 
14 void add(int u,int v) {
15     e[++tot]=(edge){v,h[u]};
16     h[u]=tot;
17 }
18 
19 int lca(int x,int y) {
20     for (++tim;;swap(x,y)) if (x) {
21         x=find(x);
22         if (tic[x]==tim) return x; else tic[x]=tim,x=pre[match[x]];
23     }
24 }
25 
26 void shrink(int x,int y,int p) {
27     while (find(x)!=p) {
28         pre[x]=y,y=match[x];
29         if (tp[y]==2) tp[y]=1,que[++qr]=y;
30         if (find(x)==x) f[x]=p;
31         if (find(y)==y) f[y]=p;
32         x=pre[y];
33     }
34 }
35 
36 bool aug(int s) {
37     for (int i=1;i<=n;++i) f[i]=i;
38     memset(tp,0,sizeof tp),memset(pre,0,sizeof pre);
39     tp[que[ql=qr=1]=s]=1; // 1: type A ; 2: type B
40     int t=0;
41     while (ql<=qr) {
42         int x=que[ql++];
43         for (int i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v) {
44             if (find(v)==find(x) || tp[v]==2) continue; 
45             if (!tp[v]) {
46                 tp[v]=2,pre[v]=x;
47                 if (!match[v]) {
48                     for (int now=v,last,tmp;now;now=last) {
49                         last=match[tmp=pre[now]];
50                         match[now]=tmp,match[tmp]=now;
51                     }
52                     return true;
53                 } 
54                 tp[match[v]]=1,que[++qr]=match[v];
55             } else if (tp[v]==1) {
56                 int l=lca(x,v);
57                 shrink(x,v,l);
58                 shrink(v,x,l);
59             }
60         }
61     }   
62     return false;
63 }
64 
65 void dfs(int x) {
66     id[x]=scc; siz[scc]++;
67     for (int i=h[x];i;i=e[i].nxt) {
68         int y=e[i].v;
69         if (!id[y]) dfs(y);
70     }
71 }
72 
73 int main()
74 {
75     while (scanf("%d",&n)!=EOF) {
76         for (int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
77         scanf("%d",&L);
78         tim=scc=tot=0;
79         for (int i=1;i<=n;i++) h[i]=match[i]=tp[i]=f[i]=tic[i]=pre[i]=0;
80         for (int i=1;i<=n;i++)
81             for (int j=i+1;j<=n;j++)
82                 if (abs(x[i]-x[j])+abs(y[i]-y[j])<=L) add(i,j),add(j,i);
83         
84         for (int i=1;i<=n;i++) siz[i]=num[i]=id[i]=0;
85         for (int i=1;i<=n;i++) 
86             if (!id[i]) scc++,dfs(i);
87         
88            for (int i=1;i<=n;++i) num[id[i]]+=(!match[i] && aug(i));
89            
90         bool ok=1;
91         for (int i=1;i<=scc;i++)
92             if (num[i]*2!=siz[i]) ok=0;
93         printf("%s\n",ok?"YES":"NO");    
94     }
95     
96     return 0;
97 }
View Code

BZOJ 4405 / Luogu 4258

the m frames n balls. To put a ball in each box, and each box can hold up to three balls. Define a number of balls box <= 1 as the air, to ask the best block matching scheme allows most of the air. This question is very wonderful, konjac bloggers do not have daily, problem solution reference https://blog.csdn.net/qq_30974369/article/details/79822551 the big brother.

The chiefs of the analysis very well. FIG embodiment is built: each basket split into three points, linked to each other side between points. Each ball is a point, it can be put to the basket even ripped out the three point edge . After such ships built FIG run FIG matching results in the maximum to ensure that all balls have matching case, the  maximum number of matches = + match the number of balls contribute basket itself . Then the problem is solved.

Luo Valley This question also requires reasonable solution right output, the program will be saved in the process of matching with trees and flowers. Note that as long as the matching process to ensure that the first match ball with the handle of the basket, and then deal with the basket match basket , so as to ensure the greatest contribution in the case of the ball has to match (reflected in the blogger program is the main program first loop for recirculating ball matching the matching process in the basket). Otherwise, seek out the contribution is right, but the program does not count.

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=605;
 4 const int M=N*N*2;
 5 int n,n1,n2,m,que[M],ql,qr,pre[N],tim=0;
 6 int h[N],tot=0;
 7 int match[N],f[N],tp[N],tic[N];
 8 struct edge {
 9     int v,nxt;
10 } e[M];
11 
12 int find(int x) { return f[x]==x?f[x]:f[x]=find(f[x]); }
13 
14 void add(int u,int v) {
15     e[++tot]=(edge){v,h[u]};
16     h[u]=tot;
17 }
18 
19 int lca(int x,int y) {
20     for (++tim;;swap(x,y)) if (x) {
21         x=find(x);
22         if (tic[x]==tim) return x; else tic[x]=tim,x=pre[match[x]];
23     }
24 }
25 
26 void shrink(int x,int y,int p) {
27     while (find(x)!=p) {
28         pre[x]=y,y=match[x];
29         if (tp[y]==2) tp[y]=1,que[++qr]=y;
30         if (find(x)==x) f[x]=p;
31         if (find(y)==y) f[y]=p;
32         x=pre[y];
33     }
34 }
35 
36 bool aug(int s) {
37     for (int i=1;i<=n;++i) f[i]=i;
38     memset(tp,0,sizeof tp),memset(pre,0,sizeof pre);
39     tp[que[ql=qr=1]=s]=1; // 1: type A ; 2: type B
40     int t=0;
41     while (ql<=qr) {
42         int x=que[ql++];
43         for (int i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v) {
44             if (find(v)==find(x) || tp[v]==2) continue; 
45             if (!tp[v]) {
46                 tp[v]=2,pre[v]=x;
47                 if (!match[v]) {
48                     for (int now=v,last,tmp;now;now=last) {
49                         last=match[tmp=pre[now]];
50                         match[now]=tmp,match[tmp]=now;
51                     }
52                     return true;
53                 } 
54                 tp[match[v]]=1,que[++qr]=match[v];
55             } else if (tp[v]==1) {
56                 int l=lca(x,v);
57                 shrink(x,v,l);
58                 shrink(v,x,l);
59             }
60         }
61     }   
62     return false;
63 }
64 
65 int id(int y,int t) { return n1+(y-1)*3+t; }
66 
67 int main()
68 {
69     int T; cin>>T;
70     while (T--) {
71         scanf("%d%d%d",&n1,&n2,&m);
72         n=n1+n2*3;
73         tim=tot=0;
74         for (int i=1;i<=n;i++) h[i]=match[i]=tp[i]=f[i]=tic[i]=pre[i]=0;
75            for (int i=1;i<=m;++i) {
76                int x,y; scanf("%d%d",&x,&y);
77                 add(x,id(y,1)),add(id(y,1),x);
78                add(x,id(y,2)),add(id(y,2),x);
79                add(x,id(y,3)),add(id(y,3),x);
80         }
81         for (int i=1;i<=n2;i++) {
82             add(id(i,1),id(i,2)),add(id(i,2),id(i,1));
83             add(id(i,1),id(i,3)),add(id(i,3),id(i,1));
84             add(id(i,2),id(i,3)),add(id(i,3),id(i,2));
85         }
86         int ans=0;
87         for (int i=1;i<=n;++i) ans+=(!match[i] && aug(i));
88            printf("%d\n",ans-n1);
89         //for (int i=1;i<=n1;++i) printf("%d ",(match[i]-n1-1)/3+1);
90         //puts("");
91     }
92     return 0;
93 }
View Code

 

Guess you like

Origin www.cnblogs.com/clno1/p/11240257.html