2018上海金马五校_J_小Y写文章(二分+二分图匹配)

版权声明: https://blog.csdn.net/yyy_3y/article/details/80012584

传送门

思路: 添加一些(n+1-m 个)假广告与不必填坑位匹配,check 条件最大匹配
=n+1,因此可以直接二分图匹配。

#include<bits/stdc++.h>
using namespace std;
const int N=500;
int tx[N],ty[N];
int w[N][N],match[N],vis[N];
int n,m;
void add_edge()
{
    memset(w,0,sizeof w);
    for(int i=1;i<=m;i++){
        for(int j=1;j<n;j++){
            w[i][j]=max(fabs(tx[j]-ty[i]),fabs(tx[j+1]-ty[i]));
        }
    }
    for(int i=1;i<=m;i++){
        w[i][0]=abs(tx[1]-ty[i]);
        w[i][n]=abs(tx[n]-ty[i]);
    }

    for(int i=m+1;i<=n+1;i++){
        for(int j=1;j<n;j++){
            w[i][j]=abs(tx[j+1]-tx[j]);
        }
    }
}
int dfs(int now,int val)
{
    for(int i=0;i<=n;i++){
        if(!vis[i] && w[now][i]<=val){
            vis[i]=1;
            if(match[i]==-1 || dfs(match[i],val)) {
                match[i]=now;
                return 1;
            }
        }
    }
    return 0;
}
bool check(int val)
{
    int ans=0;
    memset(match,-1,sizeof match);
    for(int i=1;i<=n+1;i++){
        memset(vis,0,sizeof vis);
        if(dfs(i,val)) ans++;
    }
    if(ans==n+1) return 1;
    return 0;
}
int main ()
{
    //yyy_3y
    int T; scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&tx[i]);
        for(int i=1;i<=m;i++) scanf("%d",&ty[i]);
        add_edge();
        int l=0, r=1e9+7;
        while(l<=r){
            int mid=(l+r)/2;
            if(check(mid)) r=mid-1;
            else l=mid+1;
        }
        printf("%d\n",l);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yyy_3y/article/details/80012584