A long time ago to learn what is a flower tree, today did a set of questions, finally looked at, but the current level is to understand its general thinking, as to the details of implementation, is really powerless.
Here are a few explanations for the blog:
An algorithm with Flower tree for non-direction graph matching
With Flower tree (general Graph maximum match)
In the winter camp in Beijing, Yby mentioned the "Flowering Tree blossom" algorithm to solve the maximum matching of non-binary graphs.
So, I'm going to look at what this thing is. In fact, I've got a rough idea about the algorithm, but ... Really afraid to write.
A man named Galil Zvi (should be called a computer science) wrote a paper:
Efficient algorithms for finding maximal Matching in Graphs
(If you can't find it on the Internet, you can: Http://builtinclz.abcz8.com/art/2012/Galil zvi.pdf)
This paper is really god, it solves 4 questions:
(General graph + binary graph) (maximum matching + maximum weight matching) problem.
The idea of the algorithm, the story, please read the paper yourself.
This paper tells us a lot of interesting things, such as:
The time complexity of binary graph matching with dinic is actually O (m*n^0.5), which may explain why general network flow algorithms are faster than hungry.
In addition, it is difficult to prove the correctness of the algorithm with Flower tree, and its time complexity can be done O (m*n^0.5), but to be implemented in detail, so fast to "ACM the longest thesis award."
I wrote an example code:
Http://builtinclz.abcz8.com/art/2012/ural1099.cpp
Yes, this is to solve the problem of Ural 1099 Work schedule. Time complexity is O (n^3)
Briefly describe the "tree with Flowers" algorithm:
Its core idea is to find an augmented path. Assuming that a bunch of points have been matched, we start by using BFS to build the search tree, starting with a node s that does not match. Whenever you find a node u, if you have not yet been matched, then you can do a successful augmentation; otherwise, we will connect the node U and its Mate V to the tree, and then drop v into the queue to continue searching. We give each point on the search tree a type: s or T. When you throw its Mate V into the queue, we mark u as T, and V in S-type. So the search tree looks like this:
S
/ \
A b
| |
C D
/ \ / \
E F U J
| | | |
I J v K
Of these, the two dots connected by the black vertical are already matched, and the blue slash indicates that there is an edge between the two points, but there is no pairing. T-type with red, S-type with black.
Here's a small problem: an S-type point D finds a point u when it expands, and if you are already on the search tree (that is, the ring appears), what to do.
We stipulate that if u is of type T, it ignores this discovery; (this means that we have found a ring with an even length, which is directly ignored)
S
/ \
A b
| |
C D If the edge is pointed to the T-shaped point, ignore this side.
/ \ / \
E f<-g
| | |
I j K
Otherwise, we find a ring with an odd length, and we need to do a "shrink" operation. The so-called shrinking flower operation, is to shrink this ring into a point.
S
/ \
A b
| |
C D
/ \ / \
E F | g
| | | |
I u<-+ K
This figure shrinks into 5 dots (a larger point, or a flower, plus 4 points):
After the reduction point is completed, the T-type points in the original ring are changed into S-type points and then thrown into the queue.
+-------------+
| |
| s |
|/\|
| a B |
| | | | |-It's a point now. Or an S-point.
| c D |
|/\/\|
+-|--F--u---|---+
| | | |
| | | |
| | | |
| +-------------+ |
| |
E g
| |
I K
Why do you shrink to a point. We look at a ring with an odd length (for example, the s-b-d-j-f-c-a-in the above image), and if we can find a degree (spouse) for any point in it, then the other points in the ring just fit in, which means that the degree of each point is equivalent. For example, suppose that we can find another spouse for the point D in the graph (for example, d ' OK), then the remaining 6 points in the loop can fit into just 3 pairs, one is not much, the other a lot (the D and d ' altogether 4 pairs are just good).
A-s-b-d-d ' a s-b d-d '
\| =>\
C-f-u C F-u
This is the source of our idea of shrinking points. A toiled computer scientist has shown that the same is the case when the graph before and after the contraction point has an augmented path.
The point of shrinking is also called a flower (blossom).
Notice that the inside of a flower may be nested with smaller flowers.
When we finally find an augmented path, we need to expand the nesting layer and restore the augmented path on the original image.
Well, now you have any idea how to implement this algorithm.
Oh, my God, I want to shrink a little bit ... Write about who died ...
I thought the same thing at first.
I took a look at some of Daniel's programs on the internet and then combined my own ideas and worked very hard to write a version of AC.
What is the point of realization?
First, we don't "explicitly" represent flowers. We record an array of next, representing the successor on the path of the final augmentation. At the same time, we maintain a collection that indicates where each point is now at the root of the flower (a flower is not counted after another flower is indented). You also record the marks for each point.
The main program is a BFS. For each point y developed by X, it is discussed in 4 different situations:
1. XY is a spouse (not to mention husband and wife, this is a non-binary chart ...). Or XY is now a point (in a flower): direct disregard
2. Y is a T-point: direct disregard
3. Y is single: too Good to be augmented.
4. Y is an S-shaped point: a narrowing point. Shrink point.
The work to do when shrinking points:
1. Find the X and y LCA (root) p. Looking for a LCA can be used in a variety of ways ... Direct simplicity is fine.
2. In the next array, x and Y are picked up (indicating that they form a loop.) )
3. Go to P from X and Y, modify and check the set so that they all become family, and then connect the next array along the way.
The next array is fantastic. Every moment, it actually forms a number of two-way linked lists hanging together to represent the way of a flower inside.
----
/\<--+
| | |
| |<--+
V V
----------
/ \
+---+
| |
| |
+---->s <------+
How to do the maximum match of the power graph.
Read the paper ... Use a method like km, however, to give each flower another weight. It's really complicated ...
There's a guy who wrote the code, like a GPL license ... You'd better find a way to search its website to see the copyright issue; Anyway, I'll post it first:
Http://builtinclz.abcz8.com/art/2012/mwmatching.py in the winter camp in Beijing, Yby mentioned the "Flowering Tree blossom" algorithm to solve the maximum matching of non-binary graphs.
So, I'm going to look at what this thing is. In fact, I've got a rough idea about the algorithm, but ... Really afraid to write.
A man named Galil Zvi (should be called a computer science) wrote a paper:
Efficient algorithms for finding maximal Matching in Graphs
(If you can't find it on the Internet, you can: Http://builtinclz.abcz8.com/art/2012/Galil zvi.pdf)
This paper is really god, it solves 4 questions:
(General graph + binary graph) (maximum matching + maximum weight matching) problem.
The idea of the algorithm, the story, please read the paper yourself.
This paper tells us a lot of interesting things, such as:
The time complexity of binary graph matching with dinic is actually O (m*n^0.5), which may explain why general network flow algorithms are faster than hungry.
In addition, it is difficult to prove the correctness of the algorithm with Flower tree, and its time complexity can be done O (m*n^0.5), but to be implemented in detail, so fast to "ACM the longest thesis award."
I wrote an example code:
Http://builtinclz.abcz8.com/art/2012/ural1099.cpp
Yes, this is to solve the problem of Ural 1099 Work schedule. Time complexity is O (n^3)
Briefly describe the "tree with Flowers" algorithm:
Its core idea is to find an augmented path. Assuming that a bunch of points have been matched, we start by using BFS to build the search tree, starting with a node s that does not match. Whenever you find a node u, if you have not yet been matched, then you can do a successful augmentation; otherwise, we will connect the node U and its Mate V to the tree, and then drop v into the queue to continue searching. We give each point on the search tree a type: s or T. When you throw its Mate V into the queue, we mark u as T, and V in S-type. So the search tree looks like this:
S
/ \
A b
| |
C D
/ \ / \
E F U J
| | | |
I J v K
Of these, the two dots connected by the black vertical are already matched, and the blue slash indicates that there is an edge between the two points, but there is no pairing. T-type with red, S-type with black.
Here's a small problem: an S-type point D finds a point u when it expands, and if you are already on the search tree (that is, the ring appears), what to do.
We stipulate that if u is of type T, it ignores this discovery; (this means that we have found a ring with an even length, which is directly ignored)
S
/ \
A b
| |
C D If the edge is pointed to the T-shaped point, ignore this side.
/ \ / \
E f<-g
| | |
I j K
Otherwise, we find a ring with an odd length, and we need to do a "shrink" operation. The so-called shrinking flower operation, is to shrink this ring into a point.
S
/ \
A b
| |
C D
/ \ / \
E F | g
| | | |
I u<-+ K
This figure shrinks into 5 dots (a larger point, or a flower, plus 4 points):
After the reduction point is completed, the T-type points in the original ring are changed into S-type points and then thrown into the queue.
+-------------+
| |
| s |
|/\|
| a B |
| | | | |-It's a point now. Or an S-point.
| c D |
|/\/\|
+-|--F--u---|---+
| | | |
| | | |
| | | |
| +-------------+ |
| |
E g
| |
I K
Why do you shrink to a point. We look at a ring with an odd length (for example, the s-b-d-j-f-c-a-in the above image), and if we can find a degree (spouse) for any point in it, then the other points in the ring just fit in, which means that the degree of each point is equivalent. For example, suppose that we can find another spouse for the point D in the graph (for example, d ' OK), then the remaining 6 points in the loop can fit into just 3 pairs, one is not much, the other a lot (the D and d ' altogether 4 pairs are just good).
A-s-b-d-d ' a s-b d-d '
\| =>\
C-f-u C F-u
This is the source of our idea of shrinking points. A toiled computer scientist has shown that the same is the case when the graph before and after the contraction point has an augmented path.
The point of shrinking is also called a flower (blossom).
Notice that the inside of a flower may be nested with smaller flowers.
When we finally find an augmented path, we need to expand the nesting layer and restore the augmented path on the original image.
Well, now you have any idea how to implement this algorithm.
Oh, my God, I want to shrink a little bit ... Write about who died ...
I thought the same thing at first.
I took a look at some of Daniel's programs on the internet and then combined my own ideas and worked very hard to write a version of AC.
What is the point of realization?
First, we don't "explicitly" represent flowers. We record an array of next, representing the successor on the path of the final augmentation. At the same time, we maintain a collection that indicates where each point is now at the root of the flower (a flower is not counted after another flower is indented). You also record the marks for each point.
The main program is a BFS. For each point y developed by X, it is discussed in 4 different situations:
1. XY is a spouse (not to mention husband and wife, this is a non-binary chart ...). Or XY is now a point (in a flower): direct disregard
2. Y is a T-point: direct disregard
3. Y is single: too Good to be augmented.
4. Y is an S-shaped point: a narrowing point. Shrink point.
The work to do when shrinking points:
1. Find the X and y LCA (root) p. Looking for a LCA can be used in a variety of ways ... Direct simplicity is fine.
2. In the next array, x and Y are picked up (indicating that they form a loop.) )
3. Go to P from X and Y, modify and check the set so that they all become family, and then connect the next array along the way.
The next array is fantastic. Every moment, it actually forms a number of two-way linked lists hanging together to represent the way of a flower inside.
----
/\<--+
| | |
| |<--+
V V
----------
/ \
+---+
| |
| |
+---->s <------+
How to do the maximum match of the power graph.
Read the paper ... Use a method like km, however, to give each flower another weight. It's really complicated ...
There's a guy who wrote the code, like a GPL license ... You'd better find a way to search its website to see the copyright issue; Anyway, I'll post it first:
http://builtinclz.abcz8.com/art/2012/mwmatching.py
Plus a copy of the template:
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <vector > #include <cmath> #include <queue> #include <stack> #include <map> #include <set>
Include<algorithm> using namespace std;
const int maxn=300;
int N;
BOOL G[MAXN][MAXN];
int MATCH[MAXN];
BOOL INQUEUE[MAXN],INPATH[MAXN],INBLOSSOM[MAXN];
int head,tail;
int QUEUE[MAXN];
int start,finish;
int newbase;
int FATHER[MAXN],BASE[MAXN];
int Count;
void Creategraph () {int u,v;
memset (g,0,sizeof (G));
scanf ("%d", &n);
while (scanf ("%d%d", &u,&v)!=eof) {g[u][v]=g[v][u]=1;
} void Push (int u) {queue[tail++]=u;
Inqueue[u]=1;
int Pop () {int res=queue[head++];
return res;
int findcommonancestor (int u,int v) {memset (inpath,0,sizeof (Inpath));
while (true) {U=base[u];
Inpath[u]=1;
if (U==start) break;
U=father[match[u]];
} while (true) {v=base[v]; if (Inpath[v]) break;
V=FATHER[MATCH[V]];
} return v;
} void Resettrace (int u) {int V;
while (base[u]!=newbase) {v=match[u];
Inblossom[base[u]]=inblossom[base[v]]=1;
U=FATHER[V];
if (base[u]!=newbase) father[u]=v;
} void blossomcontract (int u,int v) {newbase=findcommonancestor (u,v);
memset (inblossom,0,sizeof (Inblossom));
Resettrace (U);
Resettrace (v);
if (base[u]!=newbase) father[u]=v;
if (base[v]!=newbase) father[v]=u;
for (int tu=1;tu<=n;tu++) {if (Inblossom[base[tu]]) {base[tu]=newbase; if (!
INQUEUE[TU]) Push (TU);
}} void Findaugmentingpath () {memset (inqueue,0,sizeof (InQueue));
memset (father,0,sizeof (father));
for (int i=1;i<=n;i++) {base[i]=i;
} head=tail=1;
Push (start);
finish=0;
while (head<tail) {int u=pop (); for (int v=1;v<=n;v++) {if (g[u][v]&& (base[u]!=base[v)) &&MATCH[U]!=V) {if (V==start) | |
(match[v]>0) &&father[match[v]]>0) {blossomcontract (u,v);
else if (father[v]==0) {father[v]=u;
if (match[v]>0) {Push (match[v]);
else {finish=v;
Return
}}}} void Augmentpath () {int u,v,w;
U=finish;
while (u>0) {v=father[u];
W=MATCH[V];
Match[v]=u;
Match[u]=v;
U=w;
} void Edmonds () {memset (match,0,sizeof (match));
for (int u=1;u<=n;u++) {if (match[u]==0) {start=u;
Findaugmentingpath ();
if (finish>0) Augmentpath ();
}} void Printmatch () {count=0;
for (int u=1;u<=n;u++) {if (match[u]>0) count++;
printf ("%d\n", Count); for (int u=1;u<=n;u+ +) {if (U<match[u]) {printf ("%d%d\n", U,match[u]);
int main () {Creategraph ()}}
Edmonds ();//Match printmatch ();//output match return 0; }