zoukankan      html  css  js  c++  java
  • poj 1274 The Perfect Stall 解题报告

    题目链接:http://poj.org/problem?id=1274

    题目意思:有 n 头牛,m个stall,每头牛有它钟爱的一些stall,也就是几头牛有可能会钟爱同一个stall,问牛与 stall 最大匹配数是多少。

        二分图匹配,匈牙利算法入门题,留个纪念吧。

        书上看到的一些比较有用的知识点:

        增广:通俗地说,设当前二分图中,已有 x 个匹配边(也就是假设代码中match[i] 不为0的个数有x个),现在对 i 点(也就是代码中dfs中的参数 x) 指定一个匹配点 j, 由于 j 可能有匹配点设为 k(map[x][i]),必须要为k找到一个新匹配 (对应黑屏中的前两次增广,本来的match[2] 从 1 变为 2 了,因为要为牛2找stall ,遇到map[2][2]边的时候发现match[2] 有数,只能调用dfs(match[2]) 为 match[2]找另一个匹配,也就是map[1][5],发现能找到,于是match[5] = 1,match[2] 就顺利成章变为2了)。

          

          若能够找到,则表示匹配成功了x + 1 条边;若不能找到,相当于还是只有 x 个匹配边,只不过换了一种匹配方案而已,若达不到增加一条边的目的则称为对 i 增广不成功。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 
     6 using namespace std;
     7 const int maxn = 200 + 5;
     8 
     9 int map[maxn][maxn];
    10 int match[maxn];   // match[m]存储了匹配的方案, match[i] = j :仓库i里是牛j
    11 bool vis[maxn];
    12 int n, m, cnt;
    13 
    14 int dfs(int x)  // 深搜找增广路径
    15 {
    16     for (int i = 1; i <= m; i++)
    17     {
    18         if (!vis[i] && map[x][i])  // 对x的每个邻接点
    19         {
    20             vis[i] = true;
    21             if (match[i] == 0 || dfs(match[i]))  // 若 match[i] 点是一个初始值,表示i点原来没有匹配,则增广成功返回
    22             {                                     // 或者 match[i]点能重新找到一个新的匹配点
    23                 match[i] = x;                 // 保证新的匹配方案
    24                 return 1;
    25             }
    26         }
    27     }
    28     return 0;
    29 }
    30 
    31 void Hungary()
    32 {
    33     cnt = 0;
    34     for (int i = 1; i <= n; i++)  // 对 n 个点依次进行增广
    35     {
    36         memset(vis, 0, sizeof(vis));
    37         cnt += dfs(i);    // 增广成功,表示i点找到了一个匹配,多了一条匹配边
    38     }
    39 }
    40 
    41 int main()
    42 {
    43     int k, to;   // k: stall_num, to:stall_id
    44     while (scanf("%d%d", &n, &m) != EOF)
    45     {
    46         memset(map, 0, sizeof(map));
    47         memset(match, 0, sizeof(match));
    48 
    49         for (int i = 1; i <= n; i++)
    50         {
    51             scanf("%d", &k);
    52             for (int j = 1; j <= k; j++)
    53             {
    54                 scanf("%d", &to);
    55                 map[i][to] = 1;
    56             }
    57         }
    58         Hungary();
    59         printf("%d
    ", cnt);
    60     }
    61 }
  • 相关阅读:
    GoogleCpp风格指南 8)格式 _part1
    软考缉捕令
    nfc开发
    MFC 小知识总结二
    B
    UVA 10090 Marbles(扩展欧几里得)
    Android指令处理流程源代码追踪
    c语言基础学习04_条件判断语句
    教你如何解决Sublime Text 3使用中出现的中文乱码问题
    SecureCRT连接虚拟机中的Linux系统(Ubuntu)_Linux教程
  • 原文地址:https://www.cnblogs.com/windysai/p/3916955.html
Copyright © 2011-2022 走看看