• HDU


    1、男生女生一起坐过山车,每一排有两个座位,但是有个条件,就是每个女生必须找个男生做同伴一起(但是女生只愿意和某几个男生中的一个做同伴),求最多可以有多少对男女生组合坐上过山车。

    2、二分图的最大匹配,女生作为X集合(左边),男生作为Y集合(右边)

    3、

    3.1匈牙利算法(邻接矩阵):

    /*
    顶点编号从0开始的
    邻接矩阵(匈牙利算法)
    二分图匹配(匈牙利算法的DFS实现)(邻接矩阵形式)
    初始化:g[][]两边顶点的划分情况
    建立g[i][j]表示i->j的有向边就可以了,是左边向右边的匹配
    g没有边相连则初始化为0
    uN是匹配左边的顶点数,vN是匹配右边的顶点数
    左边是X集,右边是Y集
    调用:res=hungary();输出最大匹配数
    优点:适用于稠密图,DFS找增广路,实现简洁易于理解
    时间复杂度:O(VE)
    */
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    
    const int MAXN=512;
    int uN,vN;//u,v 的数目,使用前面必须赋值
    int g[MAXN][MAXN];//邻接矩阵,记得初始化
    int linker[MAXN];//linker[v]=u,表示v(右边Y集合中的点)连接到u(左边X集合中的点)
    bool used[MAXN];
    bool dfs(int u){//判断以X集合中的节点u为起点的增广路径是否存在
        for(int v=0;v<vN;v++)//枚举右边Y集合中的点
            if(g[u][v]&&!used[v]){//搜索Y集合中所有与u相连的未访问点v
                used[v]=true;//访问节点v
                if(linker[v]==-1||dfs(linker[v])){//是否存在增广路径
                    //若v是未盖点(linker[v]==-1表示没有与v相连的点,即v是未盖点),找到增广路径
                    //或者存在从与v相连的匹配点linker[v]出发的增广路径
                    linker[v]=u;//设定(u,v)为匹配边,v连接到u
                    return true;//返回找到增广路径
                }
            }
            return false;
    }
    int hungary(){//返回最大匹配数(即最多的匹配边的条数)
        int res=0;//最大匹配数
        memset(linker,-1,sizeof(linker));//匹配边集初始化为空
        for(int u=0;u<uN;u++){//找X集合中的点的增广路
            memset(used,false,sizeof(used));//设Y集合中的所有节点的未访问标志
            if(dfs(u))res++;//找到增广路,匹配数(即匹配边的条数)+1
        }
        return res;
    }
    
    int main(){
        int i,ans;
        int K,M,N;//K边数,M是左边的顶点数,N是右边的顶点数
        int u,v;
        while(~scanf("%d",&K)){
            if(K==0)break;
            scanf("%d%d",&M,&N);
            uN=M;//匹配左边的顶点数
            vN=N;//匹配右边的顶点数
            memset(g,0,sizeof(g));//二分图的邻接矩阵初始化
            for(i=0;i<K;++i){
                scanf("%d%d",&u,&v);
                g[--u][--v]=1;//顶点编号从0开始的
            }
            ans=hungary();
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    3.2匈牙利算法(邻接表):

    /*
    //顶点编号从0开始的
    匈牙利算法邻接表形式
    使用前用init()进行初始化,给uN赋值
    加边使用函数addedge(u,v)
    */
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    
    const int MAXN=512;//点数的最大值
    const int MAXM=1024;//边数的最大值
    struct Edge{
        int to,next;
    }edge[MAXM];
    int head[MAXN],tot;
    void init(){
        tot=0;
        memset(head,-1,sizeof(head));
    }
    void addedge(int u,int v){
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    int linker[MAXN];
    bool used[MAXN];
    int uN;
    bool dfs(int u){
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(!used[v]){
                used[v]=true;
                if(linker[v]==-1||dfs(linker[v])){
                    linker[v]=u;
                    return true;
                }
            }
        }
        return false;
    }
    int hungary(){
        int res=0;
        memset(linker,-1,sizeof(linker));
        //点的编号0~uN-1
        for(int u=0;u<uN;u++){
            memset(used,false,sizeof(used));
            if(dfs(u))res++;
        }
        return res;
    }
    int main(){
        int i,ans;
        int K,M,N;
        int u,v;
        while(~scanf("%d",&K)){
            if(K==0)break;
            scanf("%d%d",&M,&N);
            uN=M;//匹配左边的顶点数
            init();//初始化
            for(i=0;i<K;++i){
                scanf("%d%d",&u,&v);
                addedge(--u,--v);//顶点编号从0开始的
            }
            ans=hungary();
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    3.3匈牙利算法(邻接表,用vector实现):

    /*
    //顶点编号从1开始的
    用STL中的vector建立邻接表实现匈牙利算法
    效率比较高
    处理点比较多的效率很高。1500的点都没有问题
    */
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    #include<vector>
    using namespace std;
    
    const int MAXN=512;//这个值要超过两边个数的较大者,因为有linker
    int linker[MAXN];
    bool used[MAXN];
    vector<int>G[MAXN];
    int uN;
    bool dfs(int u)
    {
        int sz=G[u].size();
        for(int i=0; i<sz; i++)
        {
            if(!used[G[u][i]])
            {
                used[G[u][i]]=true;
                if(linker[G[u][i]]==-1||dfs(linker[G[u][i]]))
                {
                    linker[G[u][i]]=u;
                    return true;
                }
            }
        }
        return false;
    }
    
    int hungary()
    {
        int u;
        int res=0;
        memset(linker,-1,sizeof(linker));
        for(u=1; u<=uN; u++)
        {
            memset(used,false,sizeof(used));
            if(dfs(u)) res++;
        }
        return res;
    }
    
    int main()
    {
        int i,ans;
        int K,M,N;
        int u,v;
        while(~scanf("%d",&K))
        {
            if(K==0)break;
            scanf("%d%d",&M,&N);
            uN=M;//匹配左边的顶点数
            for(i=0; i<MAXN; i++)//二分图的邻接表初始化
                G[i].clear();
            for(i=0; i<K; ++i)
            {
                scanf("%d%d",&u,&v);
                G[u].push_back(v);//顶点编号从1开始的
            }
            ans=hungary();
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    3.4Hopcroft-Karp算法(邻接矩阵):

    /* *********************************************
    //顶点编号从1开始的
    二分图匹配(Hopcroft-Carp的算法)。
    初始化:g[][]邻接矩阵
    调用:res=MaxMatch();  Nx,Ny要初始化!!!
    时间复杂大为 O(V^0.5 E)
    适用于数据较大的二分匹配
    需要queue头文件
    ********************************************** */
    #include<iostream>
    #include<stdio.h>
    #include<queue>
    #include<string.h>
    using namespace std;
    const int MAXN=512;
    const int INF=1<<28;
    int g[MAXN][MAXN],Mx[MAXN],My[MAXN],Nx,Ny;
    int dx[MAXN],dy[MAXN],dis;
    bool vst[MAXN];
    bool searchP()
    {
        queue<int>Q;
        dis=INF;
        memset(dx,-1,sizeof(dx));
        memset(dy,-1,sizeof(dy));
        for(int i=1; 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 v=1; v<=Ny; v++)
                if(g[u][v]&&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 v=1; v<=Ny; v++)
            if(!vst[v]&&g[u][v]&&dy[v]==dx[u]+1)
            {
                vst[v]=1;
                if(My[v]!=-1&&dy[v]==dis) continue;
                if(My[v]==-1||DFS(My[v]))
                {
                    My[v]=u;
                    Mx[u]=v;
                    return 1;
                }
            }
        return 0;
    }
    int MaxMatch()
    {
        int res=0;
        memset(Mx,-1,sizeof(Mx));
        memset(My,-1,sizeof(My));
        while(searchP())
        {
            memset(vst,0,sizeof(vst));
            for(int i=1; i<=Nx; i++)
                if(Mx[i]==-1&&DFS(i))  res++;
        }
        return res;
    }
    
    int main()
    {
        int i,ans;
        int K,M,N;
        int u,v;
        while(~scanf("%d",&K))
        {
            if(K==0)break;
            scanf("%d%d",&M,&N);
            Nx=M;//匹配左边的顶点数
            Ny=N;//匹配右边的顶点数
            memset(g,0,sizeof(g));//二分图的邻接矩阵初始化
            for(i=0; i<K; ++i)
            {
                scanf("%d%d",&u,&v);
                g[u][v]=1;//顶点编号从1开始的
            }
            ans=MaxMatch();
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    3.5Hopcroft-Karp算法(邻接表,用vector实现):

    /*
    //顶点编号从0开始的
    二分图匹配(Hopcroft-Karp算法)
    复杂度O(squt(n)*E)
    邻接表存图,vector实现
    vector先初始化,然后加入边
    uN为左端的顶点数,使用前赋值(点编号0开始)
    */
    #include<iostream>
    #include<stdio.h>
    #include<vector>
    #include<queue>
    #include<string.h>
    using namespace std;
    
    const int MAXN=512;
    const int INF=0x3f3f3f3f;
    vector<int>G[MAXN];
    int uN;
    int Mx[MAXN],My[MAXN];
    int dx[MAXN],dy[MAXN];
    int dis;
    bool used[MAXN];
    bool SearchP(){
        queue<int>Q;
        dis=INF;
        memset(dx,-1,sizeof(dx));
        memset(dy,-1,sizeof(dy));
        for(int i=0;i<uN;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;
            int sz=G[u].size();
            for(int i=0;i<sz;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){
        int sz=G[u].size();
        for(int i=0;i<sz;i++){
            int v=G[u][i];
            if(!used[v]&&dy[v]==dx[u]+1){
                used[v]=true;
                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(used,false,sizeof(used));
            for(int i=0;i<uN;i++)
                if(Mx[i]==-1&&DFS(i))
                    res++;
        }
        return res;
    }
    
    int main(){
        int i,ans;
        int K,M,N;
        int u,v;
        while(~scanf("%d",&K)){
            if(K==0)break;
            scanf("%d%d",&M,&N);
            uN=M;//匹配左边的顶点数
            for(i=0;i<MAXN;++i)//二分图的邻接表初始化
                G[i].clear();
            for(i=0;i<K;++i){
                scanf("%d%d",&u,&v);
                G[--u].push_back(--v);//顶点编号从0开始的
            }
            ans=MaxMatch();
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ‘Host’ is not allowed to connect to this mysql server
    centos7安装mysql
    further configuration avilable 不见了
    Dynamic Web Module 3.0 requires Java 1.6 or newer
    hadoop启动 datanode的live node为0
    ssh远程访问失败 Centos7
    Linux 下的各种环境安装
    Centos7 安装 python2.7
    安装scala
    Centos7 安装 jdk 1.8
  • 原文地址:https://www.cnblogs.com/gongpixin/p/4977457.html
Copyright © 2020-2023  润新知