zoukankan      html  css  js  c++  java
  • 二分图的模板

    博客:

    匈牙利算法模板:

    #include<bits/stdc++.h>
    #define MAXN 9999
    using namespace std;
    int nx,ny;//nx表示二分图左边顶点的个数,ny表示二分图右边顶点的个数
    int m;//m代表边的条数
    int cx[MAXN],cy[MAXN];//如果有cx[i]=j,则必有cy[j]=i,说明i点和j点能够匹配
    int x,y;//x点到y点有边
    int e[MAXN][MAXN];//邻接矩阵
    int visited[MAXN];//标记数组,标记的永远是二分图右边的顶点
    int ret;//最后结果
    int point(int u)//这个函数的作用是寻找增广路和更新cx,xy数组,如果找到了增广路,函数返回1,找不到,函数返回0。
    {
        for(int v=1;v<=ny;v++)//依次遍历右边的所有顶点
        {
            if(e[u][v]&&!visited[v])//条件一:左边的u顶点和右边的v顶点有连通边,
    //条件二:右边的v顶点在没有被访问过,这两个条件必须同时满足
            {
                visited[v]=1;//将v顶点标记为访问过的
                if(cy[v]==-1||point(cy[v]))//条件一:右边的v顶点没有左边对应的匹配的点,
                {//条件二:以v顶点在左边的匹配点为起点能够找到一条增广路(如果能够到达条件二,说明v顶点在左边一定有对应的匹配点)。
                    cx[u]=v;//更新cx,cy数组
                    cy[v]=u;
                    return 1;
                }
            }
        }
        return 0;//如果程序到达了这里,说明对右边所有的顶点都访问完了,没有满足条件的。
    }
    int main()
    {
        while (cin>>m>>nx>>ny)
        {
            memset(cx,-1,sizeof(cx));//初始化cx,cy数组的值为-1
            memset(cy,-1,sizeof(cy));
            memset(e,0,sizeof(e));//初始化邻接矩阵
            ret=0;
            while (m--)//输入边的信息和更新邻接矩阵
            {
                cin>>x>>y;
                e[x][y]=1;
            }
            for(int i=1;i<=nx;i++)//对二分图左边的所有顶点进行遍历
            {
                if(cx[i]==-1)//如果左边的i顶点还没有匹配的点,就对i顶点进行匹配
                {
                    memset(visited,0,sizeof(visited));//每次进行point时,都要对visited数组进行初始化
                    ret+=point(i);//point函数传入的参数永远是二分图左边的点
                }
            }
            cout<<ret<<endl;
        }
    
    }
    View Code

    例题:hdu 1083

    代码:

    #include<iostream>
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    const int max_n=105,max_m=305;
    bool edge[max_n][max_m],vis[max_m];
    int cx[max_n],cy[max_m];
    int n,m;
    int pointn(int u)
    {
        for(int v=1;v<=m;v++)
        {
            if(edge[u][v]==1&&vis[v]==0)
            {
                vis[v]=1;
                if(cy[v]==-1||pointn(cy[v]))
                {
                    cx[u]=v;
                    cy[v]=u;
                    return 1;
                }
            }
        }
        return 0;
    }
    int main()
    {
        int  t;
        scanf("%d",&t);
        while(t--)
        {
            int res=0;
            //cout<<res<<endl;
            memset(cx,-1,sizeof(cx));
            memset(cy,-1,sizeof(cy));
            memset(edge,0,sizeof(edge));
            scanf("%d %d",&n,&m);
            for(int i=1;i<=n;i++)
            {
                int k;
                scanf("%d",&k);
                for(int j=0;j<k;j++)
                {
                    int x;
                    scanf("%d",&x);
                    edge[i][x]=1;
                }
            }
            for(int i=1;i<=n;i++)
            {
                 if(cx[i]==-1)
                 {
                       memset(vis,0,sizeof(vis));
                   res+=pointn(i);
    
                 }
    
                  // cout<<res<<endl;
            }
            if(res==n)
                printf("YES
    ");
            else
                printf("NO
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    快速排序理论---不含源码
    归并排序理论---不含源码
    希尔排序(shell)理论---不含源码
    Visual C++中error spawning cl.exe解决办法
    数据库的基础知识点---1
    冒泡排序的基础知识部分(不含源码)
    在虚拟机的Linux系统下安装wineqq
    数据变量的别名
    void*和void类型
    变量的作用域和连接性
  • 原文地址:https://www.cnblogs.com/linhaitai/p/9996921.html
Copyright © 2011-2022 走看看