zoukankan      html  css  js  c++  java
  • 过山车(二分图匹配)

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

    hdu_2063:过山车

    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 14852    Accepted Submission(s): 6544


    Problem Description
    RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了。可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐。但是,每个女孩都有各自的想法,举个例子把,Rabbit只愿意和XHD或PQK做partner,Grass只愿意和linle或LL做partner,PrincessSnow愿意和水域浪子或伪酷儿做partner。考虑到经费问题,boss刘决定只让找到partner的人去坐过山车,其他的人,嘿嘿,就站在下面看着吧。聪明的Acmer,你可以帮忙算算最多有多少对组合可以坐上过山车吗?
     
    Input
    输入数据的第一行是三个整数K , M , N,分别表示可能的组合数目,女生的人数,男生的人数。0<K<=1000
    1<=N 和M<=500.接下来的K行,每行有两个数,分别表示女生Ai愿意和男生Bj做partner。最后一个0结束输入。
     
    Output
    对于每组数据,输出一个整数,表示可以坐上过山车的最多组合数。
     
    Sample Input
    6 3 3 1 1 1 2 1 3 2 1 2 3 3 1 0
     
    Sample Output
    3
     
    Author
    PrincessSnow
     
    Source
     
    题解: 一道标准的二分图匹配,但是要注意二分图中左边和右边的点不能有重复的编号,所以如果左边的点是从0开始编号到m-1的话,男生要从m开始编号
    匈牙利算法的思路是用到递归的调用,这里每次找到一条增广路后都要将虚实线对调,所以这种找到解再对之前的路径进行操作的行为叫做回溯,回溯的语句一定要写成下面的形式:
    if(找到解)
    {
      回溯操作;//这里只是考虑最上面一个操作就可以了,假设后面的通过递归已经都解决了,类似于dfs的思路
    }
    所以找路径的核心代码就是:
    if(rm[s]==-1||find(rm[s]))
    {
      rm[s] = s;
      return 1;//返回找到了
    }
    下面给出代码:
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 #define N 1010
     6 int head[N];
     7 struct Edge{
     8     int to;
     9     int next;
    10 }edge[N*N];
    11 int Enct;
    12 void init()
    13 {
    14     memset(head,-1,sizeof(head));
    15     Enct = 0;
    16 }
    17 void add(int from , int to)
    18 {
    19     edge[Enct].to = to;
    20     edge[Enct].next = head[from];
    21     head[from] = Enct++;
    22     edge[Enct].to = from;
    23     edge[Enct].next = head[to];
    24     head[to] = Enct++;
    25 }
    26 bool vis[N*N];
    27 int k , n , m ;
    28 int rm[N*N];
    29 
    30 bool list(int s)
    31 {
    32     for(int j = head[s] ; j != -1 ; j = edge[j].next)
    33     {
    34         int tm = edge[j].to;
    35         if(vis[tm]==1) continue;
    36         vis[tm] = 1;//记得标记为未访问
    37         if(rm[tm]==-1||list(rm[tm])){
    38             rm[tm] = s;
    39             return 1;
    40         }
    41     }
    42         return 0;
    43 }
    44 int MaxMatch()
    45 {
    46     int ans = 0;
    47     for(int i = 0 ; i < m ; i++)
    48     {
    49         memset(vis,0,sizeof(vis));
    50         vis[i] = 1;//要标记刚进入的点是未访问的
    51         if(list(i)) ans++;
    52     }
    53     return ans;
    54 }
    55 int main()
    56 { 
    57     while(~scanf("%d%d%d",&k,&m,&n))
    58     {
    59         init();
    60         for(int i = 0 ;i < k ;i++)
    61         {
    62             int x, y;
    63             scanf("%d%d",&x,&y);
    64             add(x-1,y+m-1);//他们构成了一张图,所以不可以让两个点有相同的编号
    65         }
    66         int a ;
    67         scanf("%d",&a);
    68         memset(rm,-1,sizeof(rm));
    69         int ans = MaxMatch();
    70         printf("%d
    ",ans);
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    create_project.py报错问题,建议用回python2.7
    windows下执行build_native.sh报权限问题
    编辑器CocoStudio和CocosBuilder的对比
    双击判断
    Web文件的ContentType类型大全
    Java四类八种数据类型
    自己写的通过ADO操作mysql数据库
    使用Cout输出String和CString对象
    CString和string头文件
    C++连接mysql数据库的两种方法
  • 原文地址:https://www.cnblogs.com/shanyr/p/4893986.html
Copyright © 2011-2022 走看看