• hdu1150 Machine Schedule (匈牙利算法模版)


    匈牙利算法本质就是一个个的匹配,对于当前的处理的对象i,假设他的匹配对象为j,但是j已经和v匹配好了,那么就让v去找找着能不能和别人匹配

    v可以和别人匹配则i与j匹配,不能则i去找别人匹配

    另外引入几个定义和结论:

    1:最大匹配数 + 最大独立集 = n + m(n,m为二分图两边的节点数)

    2:二分图的最小顶点覆盖数 = 最大匹配数

    3:最小路径覆盖 = 最大独立集

    最大独立集是指:求一个二分图中最大的一个点集,该点集内的点互不相连。

    最小顶点覆盖是指: 在二分图中,用最少的点,让所有的边至少和一个点有关联。

    最小路径覆盖是指:

    对于一个 DAG(有向无环图),选取最少条路径,使得每个顶点属于且仅属于一条路径。路径长可以为 0(即单个点)。

    最大匹配是指:

    对于二分图的所有边,寻找一个子集,这个子集满足两个条件,
    1:任意两条边都不依赖于同一个点。
    2:让这个子集里的边在满足条件一的情况下尽量多。

     算法的证明如下:http://blog.csdn.net/yuxue_23/article/details/12224067

    然后是模版:

    bool find(int x){
        int i,j;
        for (j=1;j<=m;j++){    //扫描每个妹子
            if (line[x][j]==true && used[j]==false)      
            //如果有暧昧并且还没有标记过(这里标记的意思是这次查找曾试图改变过该妹子的归属问题,但是没有成功,所以就不用瞎费工夫了)
            {
                used[j]=1;
                if (girl[j]==0 || find(girl[j])) { 
                    //名花无主或者能腾出个位置来,这里使用递归
                    girl[j]=x;
                    return true;
                }
            }
        }
        return false;
    }
    int main(){
    for (i=1;i<=n;i++)
    {
        memset(used,0,sizeof(used));    //这个在每一步中清空
        if find(i) all+=1;
    }
      return 0;       
    }

    然后是本题代码:

    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <stack>
    #include <cmath>
    //#pragma comment(linker, "/STACK:102400000,102400000")
    using namespace std;
    #define PF(x) cout << "debug: " << x << " ";
    #define EL cout << endl;
    #define PC(x) puts(x);
    typedef long long ll;
    #define CLR(x, v) sizeof (x, v, sizeof(x))
    using namespace std;
    const int INF = 0x5f5f5f5f;
    const int  N= 1000050;
    const int maxn=110;
    int n,m,k,used[maxn],lk[maxn][maxn],mark[maxn];
    bool find(int u){
        for(int i = 1;i <= m;i++){
            if(lk[u][i]&&!used[i]){
                used[i] = 1;
                if(mark[i] == 0||find(mark[i])){
                    mark[i] = u;
                    return true;
                }
            }
    
        }
        return false;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(~scanf("%d",&n)){
            if(n == 0)
                break;
            memset(lk,0,sizeof(lk));
            memset(mark,0,sizeof(mark));
            scanf("%d%d",&m,&k);
            int i,a,b,c;
            for(i = 1;i <= k;i++){
                scanf("%d%d%d",&c,&a,&b);
                lk[a][b] = 1;
            }
            int ans=0;
            for(i = 1;i <= n;i++){
            memset(used,0,sizeof(used));
            if(find(i)) ans++;
            }
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    生成随机串码并保存到Excel中
    制作100份word表
    抓取网页图片-以本地IIS网页为实践对象
    使用xlsxwriter 创建图表chart
    照片查看器2.0
    编程注意事项-记踩过的坑
    STC12C5A60S2的定时器模式16位的时候没有自动重载功能
    Keil C51 一个警告 '=': pointer: different mspace
    RT-Thread 使用笔记二
    Keil-C51读取ROM数据
  • 原文地址:https://www.cnblogs.com/shimu/p/5799350.html
Copyright © 2020-2023  润新知