hdu2236

来源:互联网 发布:sql password 编辑:程序博客网 时间:2024/06/03 14:02
/*
分析:
    枚举+二分搜索+二分匹配。
    当n==1的时候我用了特殊处理,都不等那一个数字读入
就直接输出结果,然后就WA了一天,囧~~~
    注意把二分搜索当外循环、枚举当内循环,否则反过来
的话有可能超时哦~


                                             2012-10-29
*/














#include"stdio.h"#include"string.h"#include"stdlib.h"#include"math.h"#define N 111int 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;}elseup=mid-1;mid=(low+up)>>1;}printf("%d\n",ans);    }    return 0;}