思路:二分枚举差值,再枚举下限。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#define maxn 110
#define INF 0x3f3f3f3f
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
int g[maxn][maxn],vis[maxn],mat[maxn];
int n;
bool find(int x,int c,int m)
{
for(int i=1;i<=n;i++)
{
if(!vis[i]&&g[x][i]>=m&&g[x][i]<=m+c)
{
vis[i]=1;
if(mat[i]==-1||find(mat[i],c,m))
{
mat[i]=x;
return 1;
}
}
}
return 0;
}
int Hungary(int n)
{
int low=0;
int high=200;
int flag;
while(low<=high)
{
int mid=(low+high)/2;
for(int m=1;m<=100;m++)
{
flag=1;
int count=0;
clr(mat,-1);
for(int i=1;i<=n;i++)
{
clr(vis,0);
if(!find(i,mid,m))
{
flag=0;
break;
}
}
if(flag) break;
}
if(flag)
high=mid-1;
else low=mid+1;
}
return low;
}
int main()
{
int ca;
scanf("%d",&ca);
while(ca--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&g[i][j]);
printf("%d\n",Hungary(n));
}
return 0;
}