题目链接:无题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;
}