zoukankan      html  css  js  c++  java
  • hdu 1281

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

    思路:把棋盘的行x看成二分图左边的点,列y看成二分图右边的点,那么就把可以放车的位置看成是一条边,而二分图的最大匹配中x互不相同,y互不相同,所以每个匹配都是不同行不同列,所以最大匹配就是最多可以放的车的数量。而要判断有多少个点是必须放的,只要在得出最大匹配后,每次去掉一个匹配,再去运算看得出的结果是否与原来的最大匹配数相同,若相同就不是必须的,若不相同就是必须的。

    View Code
     1 #include<iostream>
     2 const int MAXN=110;
     3 using namespace std;
     4 int m,n,k;
     5 int X[MAXN],Y[MAXN];
     6 int cx[MAXN],cy[MAXN];
     7 int map[MAXN][MAXN];
     8 bool mark[MAXN];
     9 
    10 int dfs(int u){
    11     //考虑所以yi顶点v
    12     for(int v=1;v<=n;v++){
    13         //u与v邻接且没有被访问过
    14         if(!mark[v]&&map[u][v]){
    15             mark[v]=1;
    16             //如果v没有匹配,或者v已经匹配了,但从cy[v]出发可以找到一条增广路
    17             if(cy[v]==-1||dfs(cy[v])){
    18                 cy[v]=u;//把u匹配给v
    19                 cx[u]=v;//把v匹配给u
    20                 return 1;
    21             }
    22         }
    23     }
    24     return 0;
    25 }
    26 
    27 //匈牙利算法
    28 int MaxMatch(){
    29     int res=0;
    30     memset(cx,-1,sizeof(cx));//从1匹配开始增广,将cx,cy各元素初始化为-1.
    31     memset(cy,-1,sizeof(cy));
    32     for(int i=1;i<=n;i++){
    33         //从每个未盖点出发寻找增广路
    34         if(cx[i]==-1){
    35             memset(mark,false,sizeof(mark));
    36             //每寻找到一条增广路可使匹配数增加1
    37             if(dfs(i)){
    38                 res++;
    39             }
    40         }
    41     }
    42     return res;
    43 }
    44 
    45 int main(){
    46     int _case=1;
    47     while(~scanf("%d%d%d",&n,&m,&k)){
    48         memset(map,0,sizeof(map));
    49         for(int i=1;i<=k;i++){
    50             scanf("%d%d",&X[i],&Y[i]);
    51             map[X[i]][Y[i]]=1;
    52         }
    53         int ans=MaxMatch();//求二分图最大匹配的匈牙利算法
    54         int count=0;
    55         for(int i=1;i<=k;i++){
    56             map[X[i]][Y[i]]=0;//试着去掉每一条边
    57             int res=MaxMatch();
    58             map[X[i]][Y[i]]=1;//恢复
    59             if(res<ans)count++;//如果比先前求出的小,说明是重要点
    60         }
    61         printf("Board %d have %d important blanks for %d chessmen.\n",_case++,count,ans);
    62     }
    63     return 0;
    64 }
  • 相关阅读:
    容器源码分析之——ArrayList
    JVM详解(四)--运行时数据区:程序计数器(PC 寄存器)
    JVM详解(三)-- 运行时数据区:概述和线程
    JVM详解(二)-- 第2章 类加载器子系统
    vue组件传入样式参数
    vue重定向父路径无法向子路径传递参数
    cpp引用内部的元素指针变化问题
    无法获取vuex中对象的属性
    前端笔记收藏
    vue组件传参
  • 原文地址:https://www.cnblogs.com/wally/p/2991344.html
Copyright © 2011-2022 走看看