zoukankan      html  css  js  c++  java
  • 二分图 最大匹配 hdu 2063 poj 2226

    二分图的基本概念 一个无向图G=<V, E>,如果存在两个集合X、Y,使得X∪Y=V, X∩Y=Φ,并且每一条边e={x,y}有x∈X,y∈Y,则称G为一个二分图(bipartite graph)。常用<X, E, Y>来表示一个二分图。若对X中任一x及Y中任一y恰有一边e∈E,使e = {x, y}, 则称G为完全二分图(complete bipartite graph)。当|X| = m,|Y| = n时,完全二分图G记为Km,n

    二分图的性质: 定理:无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的长度均为偶数。 匹配:设G=<V, E>为二分图,如果M⊆E,并且M中没有任何两边有公共端点。M=Φ时称M为空匹配。 最大匹配:G的所有匹配中边数最多的匹配称为最大匹配。 完全匹配:若X(Y)中所有的顶点都是匹配M中的端点。则成M为完全匹配。若M既是X-完全匹配又是Y-完全匹配,则称M为G的完全匹配。 注意:最大匹配总是存在但未必唯一;X(Y)-完全匹配及G的完全匹配必定是最大的,但反之则不然;X(Y)-完全匹配未必存在。

    下面引入几个术语: 设G=<V, E>为二分图,M为G的一个匹配。

    1. M中边的端点称为M-顶点,其它顶点称为非M-顶点
    2. 增广路径:除了起点和终点两个顶点为非M-顶点,其他路径上所有的点都是M=顶点。而且它的边为匹配边、非匹配边交替出现。

    hdu 2063 过山车  简单的二分图最大匹配

       题目连接:  http://acm.hdu.edu.cn/showproblem.php?pid=2063

                       http://poj.org/problem?id=2226

    代码如下:

    #include <iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    #define MAX 510
    bool flag[MAX];
    int map[MAX][MAX],mark[MAX];
    int k,b,g;
    bool dfs(int x)
    {
    
        for(int i=1;i<=b;i++)
        {
            if(!map[x][i]||flag[i])//如果这两点没边 或有边但被标记过了就继续循环
                continue;
            flag[i]=1;   
            if(!mark[i]||dfs(mark[i])) //如果该点是孤立点或者不是孤立点时就搜索该点对应女生的增广路
            {
                mark[i]=x;
                return 1;
            }
        }
        return 0;
    }
    int find()
    {
        int i,sum=0;
        memset(mark,0,sizeof(mark));
        for(i=1;i<=g;i++)
        {
            memset(flag,0,sizeof(flag));
            if(dfs(i))
                sum++;
        }
        return sum;
    }
    int main()
    {
        int x,y;
        while(scanf("%d",&k)!=EOF)
        {
            if(k==0) break;
            scanf("%d%d",&g,&b);
            memset(map,0,sizeof(map));
            for(int i=1;i<=k;i++)
                {
                    scanf("%d%d",&x,&y);
                    map[x][y]=1;
                }
            printf("%d
    ",find());
        }
        return 0;
    }
    View Code
    //poj 2226
    #include <iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    #define MAX 900
    bool flag[MAX];
    int map[MAX][MAX],mark[MAX],cx[MAX][MAX],cy[MAX][MAX];
    char a[MAX][MAX];
    int n,m,nx,ny;
    bool dfs(int x)
    {
        for(int i=1;i<=ny;i++)
        {
            if(!map[x][i]||flag[i])//如果这两点没边 或有边但被标记过了就继续循环
                continue;
            flag[i]=1;
            if(!mark[i]||dfs(mark[i])) //如果该点是孤立点或者不是孤立点时就搜索该点对应女生的增广路
            {
                mark[i]=x;//标记该点连接的边
                return 1;
            }
        }
        return 0;
    }
    int find()
    {
        int i,sum=0;
        memset(mark,0,sizeof(mark));
        for(i=1;i<=nx;i++)
        {
            memset(flag,0,sizeof(flag));
            if(dfs(i))
                sum++;
        }
        return sum;
    }
    int main()
    {
        int i,j;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            getchar();
            for(i=1;i<=n;i++)
            {
    
                for(j=1;j<=m;j++)
                    a[i][j]=getchar();
                getchar();
            }
            nx=ny=0;
            for(i=1;i<=n;i++)
            {
                j=1;
                while(j<=m)
                {
                if(a[i][j]=='*')
                {
                    nx++;
                    while(a[i][j]=='*')
                        cx[i][j++]=nx;
                }
                else j++;
                }
            }
            for(j=1;j<=m;j++)
            {
                i=1;
                while(i<=n)
                {
                if(a[i][j]=='*')
                {
                    ny++;
                    while(a[i][j]=='*')
                        cy[i++][j]=ny;
                }
                else i++;
                }
            }
            memset(map,0,sizeof(map));
            for(i=1;i<=n;i++)
                for(j=1;j<=m;j++)
                if(a[i][j]=='*') map[cx[i][j]][cy[i][j]]=1;
            printf("%d
    ",find());
        }
        return 0;
    }
    View Code
  • 相关阅读:
    dotnet core 获取 MacAddress 地址方法
    dotnet core 获取 MacAddress 地址方法
    dotnet core 发布只带必要的依赖文件
    dotnet core 发布只带必要的依赖文件
    Developing Universal Windows Apps 开发UWA应用 问答
    Developing Universal Windows Apps 开发UWA应用 问答
    cmd 如何跨驱动器移动文件夹
    cmd 如何跨驱动器移动文件夹
    C++ 驱动开发 error LNK2019
    C++ 驱动开发 error LNK2019
  • 原文地址:https://www.cnblogs.com/yly921712230/p/3227418.html
Copyright © 2011-2022 走看看