M

想说的话

一开始理解错了。。。墨迹了半天不知道咋做。

然后回头去做二分图的作业,才忽然惊醒。。。n行对n列建二分图,直接跑最大匹配找minn跟maxx。然后就T了。

匈牙利的效率果然靠不住。

考虑优化,可以用二分,这里先二分差值,再跑二分图,如果能匹配上,证明答案小了,反之则答案大了。这样是O(nlogn)的。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define ms(x) memset(x,0,sizeof(x))
#define inf 0x3f3f3f3f
#define mf(x) memset(x,inf,sizeof(x))
#define mf1(x) memset(x,-1,sizeof(x))
using namespace std;
const int maxn = 100+10;
const int maxm = 10000+10;
int uu, vv;
int a[maxn][maxn];
bool used[maxn];
int girl[maxn];
bool dfs(int u,int l,int r){
    for(int v=1; v<=uu; v++){
        if(a[u][v]>=l && a[u][v]<=r && !used[v]){
            used[v]=true;
            if(girl[v]==-1||dfs(girl[v],l,r)){
                girl[v]=u;
                return 1;
            }
        }
    }
    return 0;
}
bool Dfs(int mid,int l,int r){
    int res=0;
    mf1(girl);
    for(int u=1;u<=uu;u++){
        ms(used);
        if(!dfs(u,l,r)) return 0;
    }
    return 1;
}
bool check(int mid){
    for(int i=0;i+mid<=100;i++){
        if(Dfs(mid,i,i+mid)){
            return 1;
        }
    }
    return 0;
}
int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        int n;
        scanf("%d", &n);
        uu = vv = n;
        int minn=inf,maxx=-1;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++){
                scanf("%d",&a[i][j]);
                minn=min(minn,a[i][j]);
                maxx=max(maxx,a[i][j]);
            }
        int l=0,r=maxx-minn;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid)){
                r=mid-1;
            } 
            else l=mid+1;
        }
        printf("%d
", l);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Zfio/p/12889698.html