【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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值