二分图匹配~匈牙利及HK算法

二分图当且仅当图中不存在奇数长度的环

根据上面的定理有二分图染色判定,复杂度O(N+M)

 1 void dfs(int x, int color) {
 2     v[x]=color;
 3     for(int i=head[x];i;i=nex[i]){
 4         int y=ver[i];
 5         if(!v[y]) {if(!dfs(y,3-color)) return false;}
 6         else if(v[y]==color) return false;
 7     }
 8     return true;
 9 }
10 
11 int main(){
12     bool flag=true;
13     for(int i=1;i<=n;i++) if(!v[i]) if(!dfs(i,1)) flag=false;
14 }

关于二分图匹配的算法,最基础的就是匈牙利算法,每次找一个点,看看他是否有增广路,使匹配增加,复杂度O(N*M)

 1 bool dfs(int x){
 2     for(int i=head[x];i;i=nex[i]){
 3         int y=ver[i];
 4         if(!v[y]){
 5             v[y]=1;
 6             if(!m[y] || dfs(m[y])){
 7                 m[y]=x;
 8                 return true;
 9             }
10         }
11     }
12 }
13 for(int i=1;i<=n;i++){
14     memset(v,0,sizeof(v));
15     if(dfs(i)) ans++;
16 }

HK算法是每次用M的复杂度匹配可以匹配的点,这样不再用N次,而只需要√N次即可(原因是最坏情况下N个点都匹配,每次匹配√N个匹配√N次,因为每次匹配是在上一次匹配的基础上匹配,所以匹配次数不能大于上一次,只有√N*√N才会每次用M复杂度,如果1*N只需要一次M,或者N*1也是一个M,所以最坏情况M的最坏迭代次数是√N)

 1 bool find(int x){
 2     /* 找寻所有深度右边是左边+1的点,这样就相当于找增广路,看看增广路能否增广 */
 3     for(int i=0;i<G[x].size();i++){
 4         int y=G[x][i];
 5         if(!vis[y] && dy[y]==dx[x]+1){
 6             vis[y]=true;
 7             if(!my[y] || find(my[y])){mx[x]=y;my[y]=x;return true;}
 8         }
 9     }
10     return false;
11 }
12 
13 int match(){
14     /* 初始化 */
15     memset(mx,0,sizeof(mx));
16     memset(my,0,sizeof(my));
17     int ans=0;
18     while(true){
19         /* 初始化 */
20         bool flag=false;
21         while(q.size()) q.pop();                      
22         memset(dx,0,sizeof(dx));
23         memset(dy,0,sizeof(dy));
24         /* 将所有未匹配的左边点加入队列 */
25         fore(i,1,nx) if(!mx[P[i]]) q.push(P[i]);
26         /* 将所有非匹配点进行BFS,将所有点按层次编号 */
27         while(q.size()){
28             int x=q.front();q.pop();
29             for(int i=0;i<G[x].size();i++){
30                 int y=G[x][i];
31                 if(!dy[y]){
32                     dy[y] = dx[x] + 1;
33                     /* 凡是已匹配的将被匹配的点继续层次编号 */
34                     if(my[y]) dx[my[y]]=dy[y]+1,q.push(my[y]);
35                     else flag=true;
36                 }
37             }
38         }
39         if(!flag) break;//确保有一个点是空匹配点
40         memset(vis,0,sizeof(vis));
41         fore(i,1,nx) if(!mx[P[i]] && find(P[i])) ans++;
42     }
43     return ans;
44 }
1 vector<int>G[N];
2 int nx,ny;
3 int mx[N],my[N];
4 queue<int>q;
5 int dx[N],dy[N];
6 bool vis[N];

猜你喜欢

转载自www.cnblogs.com/rign/p/11116871.html