zoukankan      html  css  js  c++  java
  • 算法设计与分析 6.3 棋盘取子

    ★题目描述

    有一个N行M列的棋盘,上面摆放有K个棋子,现在想要尽可能的从棋盘上取下这些棋子

    但是棋盘的每行每列至多允许取一个棋子,请问最多能取多少棋子?

    ★输入格式

    输入的第一行三个数字N,M,K(1<=N,M<=100,1<=K<=M*M)$,表示棋盘与棋子数。

    接下来K行每行两个数字a,b(1<=a<=N,1<=b<=M)代表一个位于a行b列的棋子。

    ★输出格式

    输出一个整数表示最多能取的棋子数目。

    ★样例输入

    2 2 4
    1 1
    1 2
    2 1
    2 2
    

    ★样例输出

    2
    

    ★提示

    ★参考代码

    /*
    这题其实是二分图最大匹配数问题
    二分图要求能够划分两个A,B子集,然后每个子集内部的点间没有联系。
    也就是说二分图中的任何一条边必须一端在A子集内,另外一端在B子集内。
    
    那么将棋盘的行 i 划分到A子集内,将棋盘的列 j 划分到B子集内
    如果棋盘在第 i 行第 j 列有一颗棋子,那么 i、j构成一条边
    这个构建出的图恰好满足二分图的条件
    
    然后题目问的最多取棋子数就是问最大匹配数
    */
    #include<bits/stdc++.h>
    using namespace std;
    
    int Match[501];
    int Visit[501];
    
    int H[501];
    struct Edge{
    	int end,nxt; 
    }E[100001];
    
    int idx=0;
    void AddEdge(int u, int v){ //用邻接表方式记录存稀疏图 
        idx++;
        E[idx].end = v;
        E[idx].nxt = H[u];
        H[u] = idx;
    }
    
    
    int find(int x) {
        for(int i=H[x]; i!=0; i=E[i].nxt) {
            int e = E[i].end;
            if(!Visit[e]){
                Visit[e] = 1;
                if(Match[e]==0 || find(Match[e])) {
                    Match[e] = x;
                    return 1;
                }
            }
        }
        return 0;//自己中意的全部都被预定了。配对失败。
    }
    
    
    int main(){
        int n,m,k;
    	scanf("%d%d%d",&n,&m,&k);
    	
    	int u,v;
    	memset(H, 0, sizeof(H));
    	while(k--){
    		scanf("%d%d",&u,&v);
    		AddEdge(u, v);
    	}
    	
    	int res=0;
    	memset(Match, 0, sizeof(Match));
    	for(int i=1; i<=n; i++) {
            memset(Visit,0,sizeof(Visit));
            res += find(i);
        }
        
        printf("%d
    ",res);
        return 0;
    } 
    
  • 相关阅读:
    中国式沟通
    10 表连接优化
    09 优化数据访问
    07 SQL优化技术
    06 执行计划
    04 系统和对象统计信息
    03 找出性能问题
    02 key concept
    Xpert 调优
    JavaWeb_常用功能_01_文件上传
  • 原文地址:https://www.cnblogs.com/yejifeng/p/12097607.html
Copyright © 2011-2022 走看看