zoukankan      html  css  js  c++  java
  • hdu2236

    hdu2236 无题II
    传送门
    在一个(n*n)的矩阵(a)中,选择(n)个不同行、不同列的元素,使得其中最大值与最小值的差值最小
    (1leq nleq 100)(0leq a_{ij} leq 100)

    由于每一行、每一列只能选择一个元素,可以将行号和列号分成两个集合,建立二分图。
    二分答案,遍历所有不同的元素,设定为下界,将矩阵中所有符合条件的元素行号和列号之间连边,通过匈牙利算法判断当前答案是否可行
    时间复杂度(O(n^4log n))

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<cstring>
    #include<string>
    #include<sstream>
    #include<cmath>
    #include<ctime>
    #include<algorithm>
    #define LL long long
    #define PII pair<int,int>
    #define PLL pair<LL,LL>
    #define pi acos(-1.0)
    #define eps 1e-6
    #define lowbit(x) x&(-x)
    using namespace std;
    
    const int maxn=110;
    int T,n,m,a[maxn][maxn],line[maxn][maxn],match[maxn],book[maxn];
    set<int> s;
    
    bool find(int u){
        for(int i=1;i<=m;i++){
            if(line[u][i] && !book[i]){
                book[i]=1;
                if(!match[i] || find(match[i])){
                    match[i]=u;
                    return true;
                }
            }
        }
        return false;
    }
    
    int matching(){
        int res=0;
        for(int i=1;i<=n;i++){
            memset(book,0,sizeof(book));
            if(find(i)) res++;
        }
        return res;
    }
    
    bool check(int diff){
        set<int>::iterator it;
        for(it=s.begin();it!=s.end();it++){
            int mini=*it;
            memset(line,0,sizeof(line));
            memset(match,0,sizeof(match));
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(a[i][j]>=mini && a[i][j]<=mini+diff) line[i][j]=1;
                }
            }
            if(matching()==n) return true;
        }
        return false;
    }
    
    int main(){
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            s.clear();
            m=n;
            int mini=110,maxi=-1;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    scanf("%d",&a[i][j]);
                    mini=min(mini,a[i][j]);
                    maxi=max(maxi,a[i][j]);
                    s.insert(a[i][j]);
                }
            }
            int l=0,r=maxi-mini;
            while(r>l){
                int mid=(l+r)>>1;
                if(check(mid)) r=mid;
                else l=mid+1;
            }
            printf("%d
    ",r);
        }
        return 0;
    }
    
  • 相关阅读:
    centos7 安装 tesseract4.1
    08 图的数据结构和算法
    07 树形结构及其算法
    05 数组与链表算法
    06 堆栈与队列算法
    04 查找与哈希算法
    03 排序算法
    javascript 标签轮播
    tomcat URI get 参数中文传到后台 乱码 URIEncoding
    javascript 标签切换
  • 原文地址:https://www.cnblogs.com/fxq1304/p/13429830.html
Copyright © 2011-2022 走看看