• GYM


    题意:有N个学生和N个老师,每个人都有自己的坐标X,Y,给每个学生匹配一个老师,要求N个匹配中的距离最大值最小。其中距离的定义为:|X − X’| + |Y − Y ‘|.

    分析:一道典型的最大值最小化的题目,可以二分逼近的方法找到最小值。二分中的check操作就用匈牙利匹配来判断。在匹配的过程中加入对边长的判断,或者直接根据边长限制建立新图。最后得到的上界就是答案。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn = 2e2+5;
    struct Node{
        LL x,y;
    }s[maxn],t[maxn];
    int N;
    struct Edge{
        LL val;
        int to,next;
    }edges[maxn<<2];
    int head[maxn],tot;
    int linker[maxn];
    bool used[maxn];
    
    void init()
    {
        tot=0;
        memset(head,-1,sizeof(head));
    }
    
    void AddEdge(int u,int v, LL val)
    {
        edges[tot].val = val;
        edges[tot].to = v;
        edges[tot].next = head[u];
        head[u] = tot++;
    }
    
    bool dfs(int u,LL limit){
        int v,st,ed;
        for(int i=head[u];~i;i = edges[i].next){
            v = edges[i].to;
            if(!used[v] && edges[i].val <=limit){
                used[v]=true;
                if(linker[v]==-1||dfs(linker[v],limit)){
                    linker[v]=u;
                    return true;
                }
            }
        }
        return false;
    }
    
    bool hungary(LL limit){
        int u;
        int res=0;
        memset(linker,-1,sizeof(linker));
        for(u=1;u<=N;u++){
            memset(used,0,sizeof(used));
            if(dfs(u,limit)) res++;
        }
        return res==N; 
    }
    
    //#define LOCAL
    int main()
    {
        #ifdef LOCAL
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
           #endif
        int T;
        LL X,Y;
        while(scanf("%d",&N)==1){
            init();
            for(int i=1;i<=N;++i)
                scanf("%lld%lld",&s[i].x,&s[i].y);
            for(int i=1;i<=N;++i)
                scanf("%lld%lld",&t[i].x,&t[i].y);
            LL mx=-1;
            for(int i=1;i<=N;++i){
                for(int j=1;j<=N;++j){
                    LL dist = abs(s[i].x-t[j].x)+abs(s[i].y-t[j].y);
                    AddEdge(i,j+N,dist);
                    AddEdge(j+N,i,dist);
                    mx = max(mx,dist);
                }
            }
            LL L=0,R=mx,mid;
            while(R-L>1){
                mid = L+(R-L)/2;
                if(hungary(mid)) R = mid;
                else L = mid;
            }
            printf("%lld
    ",R);
        }
        return 0;
    }
    为了更好的明天
  • 相关阅读:
    io学习三
    io学习二
    io学习一
    多线程学习(十五)
    spring源码阅读(四)
    多线程学习(十四)
    多线程学习(十三)
    设计模式(一)
    spring源码阅读(三)
    spring源码阅读(二)
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9320554.html
Copyright © 2020-2023  润新知