【BAPC 2016 J】 Programming Tutors 二分图 二分答案

You are the founder of the Bruce Arden Programming
Collective, which is a tutoring programme that matches
experienced programmers with newbies to teach them.
You have N students and N tutors, but now you have
to match them up. Since the students will have to travel
to their tutors’ houses from their own (or vice versa) you
decide to do your matching based on travel distance.
Minimising overall distance doesn’t seem fair; it might happen that one student has to travel
a huge distance while all the other students get a tutor very close by, even though the tutors
could have been split up so that each gets a tutor that is at least somewhat close.
Thus, you opt to minimise the distance travelled by the student who is worst off; one pairing
of students to tutors is better than another if the student who has to travel farthest in the
first pairing has to travel less far than the student who has to travel farthest in the second
pairing.
Because the students live in a city, the distance that a student needs to travel is not the
literal distance between them and their tutor. Instead, the distance between points (X, Y )
and (X0
, Y 0
) in the city is
|X − X0
| + |Y − Y
0
|.
Input
The first line of the input contains an integer N, with 1 ≤ N ≤ 100, the number of students
and the number of tutors to pair up.
Then, there are N lines, each with two space separated integers with absolute value at most
108
, which give the locations of the N students.
These are followed by N lines, each with two space separated integers with absolute value at
most 108
, which give the locations of the N tutors.
Note that it is possible for students and/or tutors to have identical locations (they may share
a house).
Output
Output a single line containing a single integer K, where K is the least integer such that there
exists a pairing of students to tutors so that no pair has distance greater than K between
them.
22 Problem J: Programming Tutors
Sample Input 1 Sample Output 1
2 2
0 0
0 3
0 2
0 5
Sample Input 2 Sample Output 2
4 2
0 1
0 2
0 3
0 4
1 0
1 1
1 2
1 3
Sample Input 3 Sample Output 3
3 5
0 5
5 2
4 5
3 3
5 2
5 2
Sample Input 4 Sample Output 4
2 10
0 0
0 5
-1 4
8 3

题意:n个学生找n个老师,只能一一匹配,问最大的曼哈顿距离最小

思路:

对距离进行二分,check函数判断最大边不超过mid时能否匹配完n对点,若可以,则继续缩小范围,反之扩大范围。

AC代码:

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e4+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'|ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };


const ll V = 1e2+10,  E = 4e4;
ll head[E],  pnt[E],  nxt[E],  cost[E],e = 1;
ll vis[E],  pre[E];

void addedge(ll u , ll v , ll c)
{
    pnt[e] = v;
    cost[e] = c;
    nxt[e] = head[u];
    head[u] = e++;
}

bool dfs(ll x, ll mid)      //匈牙利算法  二分图最大匹配
{
    for(ll i = head[x]; i ; i = nxt[i])
    {
        ll v = pnt[i];
        if(cost[i]<=mid&&!vis[v])
        {
            vis[v] = 1;
            if((!pre[v]||dfs(pre[v],mid)))
            {
                pre[v] = x;
                return true;
            }
        }
    }
    return false;
}

typedef struct Pos
{
    ll x;
    ll y;
}P;
P a[maxn][2];

ll Ed[maxn];

int main()
{
    ll n = read();
    rep(i,1,n) a[i][0].x = read(), a[i][0].y = read();
    rep(i,1,n) a[i][1].x = read(), a[i][1].y = read();
    ll L = inf, R = - inf;
    ll p = 0;
    rep(i,1,n) rep(j,1,n)
    {
        addedge(i,j+n, abs(a[i][0].x-a[j][1].x) + abs(a[i][0].y - a[j][1].y ) );
        addedge(j+n,i, abs(a[i][0].x-a[j][1].x) + abs(a[i][0].y - a[j][1].y ) );
        Ed[++p] = abs(a[i][0].x-a[j][1].x) + abs(a[i][0].y - a[j][1].y );
    }

    ll ans = inf;
    sort(Ed+1,Ed+1+p);
    L = 1, R = p;
    while(L<=R)
    {
        ll mid = (L+R)/2;
        ll cnt = 0;
        rep(i,1,n*2+2) pre[i] = 0;
        int flag = 1;
        rep(i,1,n)
        {
            rep(j,1,n*2+2) vis[j] = 0;
            if(!dfs(i,Ed[mid]))  {flag=0;break;}
        }
        if(flag) R = mid-1, ans = min(ans,Ed[mid]);
        else L = mid+1 ;
    }
    cout<<ans<<'\n';
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45492531/article/details/107541930
今日推荐