這個東西其實看看就好, \(n^3\) 次的做法雖說也是多項式複雜度但總給人很暴力的感覺...
我們都知道二分圖最大匹配可以匈牙利、網路流,因為二分圖只有一邊連向另一邊,換句話說就是不存在奇環(可以簡單證明),這是增廣路演算法可以解決的
對於有向無環圖,網路流演算法也可以跑得非常優秀,但是對於一般圖來說,這兩個演算法都束手無策了
一般圖的背景一般是一堆男生(n 個), 0 個女生,兩個男生間存在邊,表示某種關♂系,然後求最大匹配數
那麼這樣的圖中是有可能存在奇環的,奇環沒有增廣路(本來都不知道增廣路是個啥,寫這篇隨筆的時候才去看...),
這時候就要樹上開花啦~
我們考慮和匈牙利時一樣,每次幫乙個點匹配,但是這裡用的是廣搜的方式(匈牙利是深搜),建出 bfs 樹並在上面進行相應的奇環縮點操作(也就是拿出乙個點,剩下的兩兩匹配),因為可以證明奇環上任意乙個點被匹配後其他點都可以兩兩匹配
這裡的 match 如同名稱表示與誰匹配,並且這裡可以將 pre 陣列理解為備胎匹配的陣列
//by judge
#include#include#include#define rg register
#define fp(i,a,b) for(rg int i=(a),i=(b)+1;ii;--i)
#define go(g,u) for(rg int i=g.head[u],v=g.e[i].to;i;v=g.e[i=g.e[i].nxt].to)
#define ll long long
using namespace std;
const int inf=1e9+7;
const int n=503;
const int m=n*n;
typedef int arr[n];
#ifndef judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?eof:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline int read() char sr[1<<21],z[20];int ccf=-1,z;
inline void ot()
inline void print(int x,char chr=' ') int n,m,tim,ans,h,t,q[m]; arr f,vis,pre,match,ty;
struct gre[m<<1];
inline void add(int u,int v),head[u]=pat;
e[++pat]=,head[v]=pat;
}}g;
int find(int x)
inline int lca(int x,int y)
}inline void shrink(int x,int y,int k)
}bool path(int s)while(u); //修改鏈上的匹配關係
return 1;
} q[++t]=match[v],ty[match[v]]=1; //當前點匹配了,就連同匹配點一起丟到佇列中
} else
} return 0;
}int main()
模板 帶花樹
學習部落格 那些年我用帶花樹做過的題目 帶花樹板子 include using namespace std const int n 1200 10 int n,m,k inline intread namespace flowertree e 300 600 6 10 int head n tot ...
筆記 帶花樹
帶花樹用來解決一般圖的最大匹配問題。考慮不能直接增廣的原因是存在奇環。帶花樹的思路是把奇環給縮成一朵花。然後仍然通過增廣路演算法實現擴大匹配數目。其中能縮成一朵花的原因是。一堆點縮成花之後能夠成為增廣路中的某乙個點,那麼原圖也可以。這樣就簡化了模型從而可以直接用 bfs 增廣。1.uoj79 模板題...
帶花樹總結
匈牙利演算法 二分圖最大匹配 考慮一下二分圖和一般圖的最大區別 或者說唯一的區別在 二分圖沒有奇環 也就是長度為奇數的環 而一般圖是可以有的。所以匈牙利演算法中的尋找增廣路然後路徑取反的方法在一般圖上就不適用了。主要還是要解決奇環的問題。我們發現乙個奇環裡至少有乙個點不能匹配,那就乾脆把乙個奇環縮成...