hdu2236

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

由于每一行、每一列只能选择一个元素,可以将行号和列号分成两个集合,建立二分图。
二分答案,遍历所有不同的元素,设定为下界,将矩阵中所有符合条件的元素行号和列号之间连边,通过匈牙利算法判断当前答案是否可行
时间复杂度\(O(n^4\log 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\n",r);
    }
    return 0;
}
posted @ 2020-08-03 22:04  fxq1304  阅读(73)  评论(0)    收藏  举报