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
  • 相关阅读:
    iOS-远程推送
    iOS--二维码
    iOS-应用打包发布常见问题
    iOS-应用上架
    iOS-内存管理
    在Linux系统中使用蓝牙功能的基本方法
    Git服务器的Gitosis安装配置及gitignore的使用方法
    Linux系统下Git操作命令整理
    在Linux系统下使用Github的基本教程
    安装专业版的linux的方法 图解安装专业版的linux
  • 原文地址:https://www.cnblogs.com/yly921712230/p/3227418.html
Copyright © 2011-2022 走看看