zoukankan      html  css  js  c++  java
  • 二分图与网络流 带权二分图的最大匹配

    二分图与网络流  带权二分图的最大匹配

    在某书上偶然发现,二分图和网络流是有联系的,在子图u中建立超级源点,在子图v中建立超级汇点,源点到u和汇点到v的每条边容量设为1,u和v中的边的容量也设为1,求出最大流也就是原二分图的最大匹配了。

    而求带权二分图的最大匹配也就很容易了,将u和v的权值设为容量,仍然建立超级源点和超级汇点转为网络流解决即可。

    真是一切皆可网络流啊。。。

    然而。。。

    下面是xdoj1048,二分图模版测试题,匈牙利算法649ms,Hotcroft_Carp算法155ms,而转为网络流用Edmonds_Karp算法超时。。看来网络流还没学到更高级的算法之前还是不要随便将二分图的题目转为网络流了,如果是带权最大匹配就可以尝试下。

    http://acm.xidian.edu.cn/problem.php?id=1048

    匈牙利算法:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    #include<math.h>
    #include<cctype>
     
    using namespace std;
     
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000000001;
    const double Pi=acos(-1.0);
     
    int uN,vN;
    vector<int> G[maxn];
    int link[maxn];
    bool vis[maxn];
    int m;
     
    bool dfs(int u)
    {
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(!vis[v]){
                vis[v]=1;
                if(link[v]==-1||dfs(link[v])){
                    link[v]=u;
                    return true;
                }
            }
        }
        return false;
    }
     
    int hungary()
    {
        int res=0;
        memset(link,-1,sizeof(link));
        for(int u=0;u<uN;u++){
            memset(vis,0,sizeof(vis));
            if(dfs(u)) res++;
        }
        return res;
    }
     
    int main()
    {
        while(cin>>uN>>vN){
            for(int i=0;i<uN;i++) G[i].clear();
            cin>>m;
            while(m--){
                int u,v;
                cin>>u>>v;
                G[u].push_back(v);
            }
            cout<<hungary()<<endl;
        }
        return 0;
    }
     
    View Code

    Hotcroft_Carp算法:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    #include<math.h>
    #include<cctype>
     
    using namespace std;
     
    typedef long long ll;
    const int maxn=3100;
    const int INF=(1<<29);
    const double EPS=0.0000000001;
    const double Pi=acos(-1.0);
     
    int m;
    vector<int> G[maxn];
    int Mx[maxn],My[maxn],Nx,Ny;
    int dx[maxn],dy[maxn],dis;
    bool vis[maxn];
     
    bool searchP()
    {
        queue<int> q;
        dis=INF;
        memset(dx,-1,sizeof(dx));
        memset(dy,-1,sizeof(dy));
        for(int i=0;i<Nx;i++){
            if(Mx[i]==-1){
                q.push(i);
                dx[i]=0;
            }
        }
        while(!q.empty()){
            int u=q.front();
            q.pop();
            if(dx[u]>dis) break;
            for(int i=0;i<G[u].size();i++){
                int v=G[u][i];
                if(dy[v]==-1){
                    dy[v]=dx[u]+1;
                    if(My[v]==-1) dis=dy[v];
                    else{
                        dx[My[v]]=dy[v]+1;
                        q.push(My[v]);
                    }
                }
            }
        }
        return dis!=INF;
    }
     
    bool dfs(int u)
    {
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(!vis[v]&&dy[v]==dx[u]+1){
                vis[v]=1;
                if(My[v]!=-1&&dy[v]==dis) continue;
                if(My[v]==-1||dfs(My[v])){
                    My[v]=u;
                    Mx[u]=v;
                    return true;
                }
            }
        }
        return false;
    }
     
    int MaxMatch()
    {
        int res=0;
        memset(Mx,-1,sizeof(Mx));
        memset(My,-1,sizeof(My));
        while(searchP()){
            memset(vis,0,sizeof(vis));
            for(int i=0;i<Nx;i++){
                if(Mx[i]==-1&&dfs(i)) res++;
            }
        }
        return res;
    }
     
    int main()
    {
        while(cin>>Nx>>Ny){
            cin>>m;
            for(int i=0;i<Nx;i++) G[i].clear();
            memset(G,0,sizeof(G));
            while(m--){
                int u,v;
                scanf("%d%d",&u,&v);
                G[u].push_back(v);
            }
            cout<<MaxMatch()<<endl;
        }
        return 0;
    }
    View Code

    转为网络流超时的Edmonds_Karp算法:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    #include<math.h>
    #include<cctype>
     
    using namespace std;
     
    typedef long long ll;
    const int maxn=1200;
    const int INF=(1<<29);
    const double EPS=0.0000000001;
    const double Pi=acos(-1.0);
     
    int uN,vN;
    int m;
    int cap[maxn][maxn],flow[maxn][maxn];
    int s,t;
     
    int Edmonds_Karp(int s,int t)
    {
        int f=0;
        int p[maxn],a[maxn];
        queue<int> q;
        memset(flow,0,sizeof(flow));
        while(1){
            memset(a,0,sizeof(a));
            a[s]=INF;
            q.push(s);
            while(!q.empty()){
                int u=q.front();q.pop();
                for(int v=0;v<=t;v++){
                    if(!a[v]&&cap[u][v]-flow[u][v]>0){
                        q.push(v);
                        p[v]=u;
                        a[v]=min(a[u],cap[u][v]-flow[u][v]);
                    }
                }
            }
            if(a[t]==0) return f;
            for(int u=t;u!=s;u=p[u]){
                flow[p[u]][u]+=a[t];
                flow[u][p[u]]-=a[t];
            }
            f+=a[t];
        }
    }
     
    int main()
    {
        while(cin>>uN>>vN){
            s=uN+vN;
            t=s+1;
            cin>>m;
            memset(cap,0,sizeof(cap));
            while(m--){
                int u,v;
                scanf("%d%d",&u,&v);
                v+=uN;
                cap[u][v]=1;
            }
            for(int u=0;u<uN;u++) cap[s][u]=1;
            for(int v=uN;v<uN+vN;v++) cap[v][t]=1;
            cout<<Edmonds_Karp(s,t)<<endl;
        }
        return 0;
    }
     
    View Code
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    Django配置MySQL数据库教程
    给大家发个Python和Django的福利吧,不要钱的那种~~~
    Django 设置admin后台表和App(应用)为中文名
    Django 配置JWT认证方式
    威联通(NAS)应用篇:自建OwnCloud网盘(百度网盘,拜拜~~~)
    请不要浪费你的生命,一文多发推广就用它(OpenWrite)
    Django ORM 查询表中某列字段值
    【Django 2.2文档系列】Model 外键中的on_delete参数用法
    嵌入式、C语言位操作的一些技巧汇总
    【RT-Thread笔记】IO设备模型及GPIO设备
  • 原文地址:https://www.cnblogs.com/--560/p/4550578.html
Copyright © 2011-2022 走看看