hdu2236

/*
分析:
    枚举+二分搜索+二分匹配。
    当n==1的时候我用了特殊处理,都不等那一个数字读入
就直接输出结果,然后就WA了一天,囧~~~
    注意把二分搜索当外循环、枚举当内循环,否则反过来
的话有可能超时哦~


                                             2012-10-29
*/














#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"math.h"
#define N 111
int n;
int dir[N],k_dir,hash[N],hash_bot[N],num[N];
int map[N][N];
int visit[N],match[N];

struct Eage
{
    int from,to,next;
}eage[N*N];
int tot,head[N];

void add(int a,int b)
{
    eage[tot].from=a;
    eage[tot].to=b;
    eage[tot].next=head[a];
    head[a]=tot++;
}
void getmap()
{
    int i,l;
    int t;
    tot=0;
    memset(head,-1,sizeof(head));
    memset(hash,0,sizeof(hash));
    memset(hash_bot,0,sizeof(hash_bot));
    for(i=0;i<n;i++)
    for(l=0;l<n;l++)
    {
        scanf("%d",&map[i][l]);
        hash[map[i][l]]=1;
        hash_bot[map[i][l]]=1;
        add(i,l);
    }
    t=0;
    for(i=0;i<=100;i++)	if(hash[i])	num[t++]=i;
    memset(hash,0,sizeof(hash));
    for(i=1;i<t;i++)
    for(l=0;l<i;l++)
        hash[abs(num[i]-num[l])]=1;
    for(k_dir=0,i=100;i>=0;i--)		if(hash[i])	dir[k_dir++]=i;
    if(t==1)    dir[k_dir++]=0;
}
int DFS(int k,int bot,int limit)
{
    int j,v;
    for(j=head[k];j!=-1;j=eage[j].next)
    {
        v=eage[j].to;
        if(visit[v])			continue;
		if(map[k][v]<bot)		continue;
		if(map[k][v]-bot>limit)	continue;
        visit[v]=1;
        if(match[v]==-1 || DFS(match[v],bot,limit))
        {
            match[v]=k;
            return 1;
        }
    }
    return 0;
}
int main()
{
    int T;
    int i,l;
    int low,up,mid;
    int flag,ans;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        getmap();
        if(n==1)    {printf("0\n");continue;}

		ans=dir[0];
		low=0;up=k_dir-1;mid=(low+up)>>1;
		while(low<=up)
		{
			for(i=0;i<=100;i++)
			{
				if(hash_bot[i]==0)	continue;
				flag=1;
				memset(match,-1,sizeof(match));
				for(l=0;l<n;l++)
				{
					memset(visit,0,sizeof(visit));
					if(DFS(l,i,dir[mid])==0)	{flag=0;break;}
				}
				if(flag)	break;
			}
			if(flag)	{ans=ans>dir[mid]?dir[mid]:ans;low=mid+1;}
			else		up=mid-1;
			mid=(low+up)>>1;
		}
		printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值