zoukankan      html  css  js  c++  java
  • HDU1498 枚举+二分图类棋盘问题(最大匹配)

     1 /*HDU1498
     2 题目大意:
     3 给出N*N(100以内)的矩阵,矩阵上填气球的标号(1--50),给定 K
     4 问,哪些编号的气球是不能一次在K次以内拿完的。每次拿取的过程是:选择一行或者一列,再在其中选一个气球,其余的下一次不能再选。
     5 
     6 思考:
     7 变种的棋盘问题。
     8 但是要枚举气球编号(分类讨论).
     9 这样,就是找到最大的匹配,即最多能放置互不在同一行或一列的气球。
    10 这个匹配数小于等于K,则气球能全部被拿完。
    11 复杂度为:O(50*200*200)
    12 */
    13 #include <iostream>
    14 #include <cmath>
    15 #include <algorithm>
    16 #include <string.h>
    17 #include <stdio.h>
    18 #include <set>
    19 #include <stack>
    20 #include <vector>
    21 #define maxn 210
    22 using namespace std;
    23 vector<int> G[maxn];
    24 int match[maxn];
    25 bool visit[maxn];
    26 int ans[55];
    27 int mat[maxn][maxn];
    28 int cnt;
    29 int N,K;
    30 void read(){
    31     for(int i=1;i<=N;i++){
    32         for(int j=1;j<=N;j++) scanf("%d",&mat[i][j]);
    33     }
    34 }
    35 void init(int k){
    36     for(int i=1;i<=2*N;i++) G[i].clear();
    37     for(int i=1;i<=N;i++){
    38         for(int j=1;j<=N;j++){
    39             if (mat[i][j]==k){
    40                 int a=i,b=j+N;
    41                 G[a].push_back(b);
    42                 G[b].push_back(a);
    43             }
    44         }
    45     }
    46 }
    47 bool dfs(int s)//找到从s点出发的可增广路
    48 {
    49     for(int i=0;i<G[s].size();i++){
    50         int v=G[s][i];
    51         if (!visit[v]){
    52             visit[v]=true;
    53             if (match[v]==0 || dfs(match[v])){//说明v对应的项有增广路
    54                 match[v]=s;//修改v的对应项(即互斥点)是s
    55                 return true;
    56             }
    57         }
    58     }
    59     return false;
    60 }
    61 
    62 int hungary(){
    63     int ans=0;
    64     memset(match,0,sizeof(match));//清空匹配
    65     for(int i=1;i<=2*N;i++){
    66         memset(visit,0,sizeof(visit));//注意清空增广路
    67         if (dfs(i)) ans++;
    68     }
    69     return ans/2;
    70 }
    71 void solve(){
    72     cnt=0;
    73     for(int i=1;i<=50;i++){
    74         init(i);
    75         if (hungary()>K) ans[cnt++]=i;
    76     }
    77 }
    78 int main(){
    79     while(cin>>N>>K){
    80         if (!N && !K) break;
    81         read();
    82         solve();
    83         if (cnt==0) puts("-1");
    84         else {
    85             for(int i=0;i<cnt;i++)
    86             if (i==cnt-1) printf("%d
    ",ans[i]);else printf("%d ",ans[i]);
    87         }
    88     }
    89 }
  • 相关阅读:
    【洛谷3214】[HNOI2011] 卡农(思维)
    【洛谷2609】[ZJOI2012] 数列(高精度)
    【洛谷4501】[ZJOI2018] 胖(二分+RMQ)
    【洛谷4726】【模板】多项式指数函数(多项式 exp)
    uC/OS-II之入门与介绍20160525
    [转]Delphi 关键字详解
    [转]单元文件结构
    Delphi ComboBox的属性和事件、及几个鼠标事件的触发
    Delphi 用ToolButton和MonthCalendar实现DateTimePicker的功能
    Delphi 动态改变Rzsplitter的Orientation(方向)属性
  • 原文地址:https://www.cnblogs.com/little-w/p/3648356.html
Copyright © 2011-2022 走看看