http://acm.hdu.edu.cn/showproblem.php?pid=2236
找n个数使得这n个数都在不同的行和列里显然是二分图模型。难点在于求最大值与最小值差值最小。这里二分差值(看的题解),进行试探是否可以匹配成功。
#include <stdio.h>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#define LL long long
#define _LL __int64
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1000000007;
const int maxn = 110;
int n;
int G[maxn][maxn];
int Max,Min;
int cur,mid;
int match[10010],chk[10010];
int dfs(int p)
{
for(int i = 1; i <= n; i++)
{
if(!chk[i] && G[p][i] >= cur && G[p][i] <= cur+mid)
{
chk[i] = 1;
if(match[i] == -1 || dfs(match[i]))
{
match[i] = p;
return 1;
}
}
}
return 0;
}
int OK(int cur)
{
memset(match,-1,sizeof(match));
for(int i = 1; i <= n; i++)
{
memset(chk,0,sizeof(chk));
if(!dfs(i))
return 0;
}
return 1;
}
int main()
{
int test;
scanf("%d",&test);
while(test--)
{
scanf("%d",&n);
Max = -1;
Min = 110;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
scanf("%d",&G[i][j]);
if(G[i][j] > Max)
Max = G[i][j];
if(G[i][j] < Min)
Min = G[i][j];
}
}
int l,r;
l = 0;
r = Max - Min;
int res;
while(l <= r)
{
mid = (l+r) >> 1;
int flag = 0;
for(cur = Min; cur + mid <= Max; cur++) //枚举最小值,检查当前差值是否可以匹配成功
{
if( OK(cur) )
{
flag = 1;
break;
}
}
if(flag) //匹配成功,更新r
{
res = mid;
r = mid-1;
}
else
l = mid+1;//匹配不成功,更新l
}
printf("%d\n",res);
}
return 0;
}