hdoj 2236 无题II

来源:互联网 发布:建筑设计mars软件简介 编辑:程序博客网 时间:2024/04/29 11:44

题目链接:无题II

题目大意:有一个n*n的矩阵,问能不能选n个数,这n个数行和列都不同,而且最大值和最小值之间的差尽可能需要小,问这个最小差值

题目思路:我们去二分这个这个差值,然后枚举下界,判断符合条件的数,然后行和列连接一条边,然后跑一个二分图最大匹配看是不是n就好了

#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;const int maxn = 110;int line[maxn][maxn],used[maxn],nxt[maxn];int mat[maxn][maxn],num[maxn],cnt;int T,n;bool Find(int x){    for(int i = 1;i <= n;i++){        if(line[x][i]&&!used[i]){            used[i] = 1;            if(nxt[i] == 0||Find(nxt[i])){                nxt[i] = x;                return true;            }        }    }    return false;}int match(){    int sum = 0;    for(int i = 1;i <= n;i++){        memset(used,0,sizeof(used));        if(Find(i)) sum++;        else break;    }    return sum;}void handle(int x){    for(int i = 0;i < cnt;i++){        if(num[i] == x) return ;    }    num[cnt++] = x;}bool judge(int mid){    for(int i = 0;i < cnt;i++){        memset(line,0,sizeof(line));        for(int j = 1;j <= n;j++){            for(int k = 1;k <= n;k++){                if(mat[j][k] >= num[i]&&mat[j][k] <= num[i]+mid)                    line[j][k] = 1;            }        }        memset(nxt,0,sizeof(nxt));        int ans = match();        if(ans == n) return true;    }    return false;}int main(){    scanf("%d",&T);    while(T--){        cnt = 0;        scanf("%d",&n);        for(int i = 1;i <= n;i++){            for(int j = 1;j <= n;j++){                scanf("%d",&mat[i][j]);                handle(mat[i][j]);            }        }        int l = 0,r = 210,ans;        sort(num,num+cnt);        while(l <= r){           int mid = (l+r)>>1;           if(judge(mid)) ans = mid,r = mid-1;           else l = mid+1;        }        printf("%d\n",ans);    }    return 0;}
原创粉丝点击