无题II---hdu2236(二分,匈牙利)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2236

 

要求最大值与最小值的差值最小,是通过枚举边的下限和上限来完成

只需要用二分找一个区间,然后不断枚举这个区间是否可以达到最大匹配,一直二分到答案为止。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
#include<algorithm>
using namespace std;
#define N 110
#define INF 0xfffffff

int maps[N][N], n, Min, Max, ans, used[N], vis[N];

bool Find(int u)
{
    for(int i=1; i<=n; i++)
    {
        if(!vis[i] && maps[u][i]>=Min && maps[u][i]<=Max)
        {
            vis[i] = 1;
            if(!used[i] || Find(used[i]))
            {
                used[i] = u;
                return true;
            }
        }
    }
    return false;
}
bool xyl()
{
    memset(used, 0, sizeof(used));
    for(int i=1; i<=n; i++)
    {
        memset(vis, 0, sizeof(vis));
        if(!Find(i))
            return false;
    }
    return true;
}
int main()
{
    int T, MinL, MaxR;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        MaxR = 0;
        MinL = INF;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                scanf("%d", &maps[i][j]);
                MinL = min(maps[i][j], MinL);
                MaxR = max(maps[i][j], MaxR);
            }
        }
        int L = 0;
        int R = MaxR - MinL;
        ans = 0;
        while(L<=R)
        {
            int flag = 0;
            int i,Mid=(L+R)/2;
            for(i=MinL; i+Mid<=MaxR; i++)///
            {
                Min = i;
                Max = i + Mid;
                if(xyl())///说明可能还有比mid还小的差;
                {
                    flag = 1;
                    break;
                }
            }
            if(flag)
            {
                ans=Mid;
                R=Mid-1;
            }
            else
                L=Mid+1;
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

posted @ 2015-08-15 09:41  西瓜不懂柠檬的酸  Views(284)  Comments(0Edit  收藏  举报
levels of contents