二分图最大匹配

C - 2D Plane 2N Points
Time limit : 2sec / Memory limit : 256MB

Score : 400 points

Problem Statement
On a two-dimensional plane, there are N red points and N blue points. The coordinates of the i-th red point are (ai,bi), and the coordinates of the i-th blue point are (ci,di).

A red point and a blue point can form a friendly pair when, the x-coordinate of the red point is smaller than that of the blue point, and the y-coordinate of the red point is also smaller than that of the blue point.

At most how many friendly pairs can you form? Note that a point cannot belong to multiple pairs.

Constraints
All input values are integers.
1≤N≤100
0≤ai,bi,ci,di<2N
a1,a2,…,aN,c1,c2,…,cN are all different.
b1,b2,…,bN,d1,d2,…,dN are all different.
Input
Input is given from Standard Input in the following format:

N
a1 b1
a2 b2
:
aN bN
c1 d1
c2 d2
:
cN dN
Output
Print the maximum number of friendly pairs.

Sample Input 1
Copy
3
2 0
3 1
1 3
4 2
0 4
5 5
Sample Output 1
Copy
2
For example, you can pair (2,0) and (4,2), then (3,1) and (5,5).

Sample Input 2
Copy
3
0 0
1 1
5 2
2 3
3 4
4 5
Sample Output 2
Copy
2
For example, you can pair (0,0) and (2,3), then (1,1) and (3,4).

Sample Input 3
Copy
2
2 2
3 3
0 0
1 1
Sample Output 3
Copy
0
It is possible that no pair can be formed.

Sample Input 4
Copy
5
0 0
7 3
2 2
4 8
1 6
8 5
6 9
5 4
9 1
3 7
Sample Output 4
Copy
5
Sample Input 5
Copy
5
0 0
1 1
5 5
6 6
7 7
2 2
3 3
4 4
8 8
9 9
Sample Output 5
Copy
4
Submit

从两个点集合选取两个点作匹配,要得到最大匹配,很显然的二分图最大匹配。跑一遍dinic即可。

#include <iostream>
#include <string>
#include <set>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <set>
#include <map>
#include <vector>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f
struct point {
    int a, b;
}r[105],b[105];
struct edge {
    int x, f, t;
};
vector<edge> G[205];
int s, t, level[205], iter[205];
void addedge(int x,int y,int value){
    G[x].push_back(edge{y,value,(int)G[y].size()});
    G[y].push_back(edge{ x,0,(int)G[x].size() - 1 });
}
void bfs() {
    queue<int> q;
    q.push(s);
    level[s] = 0;
    while (!q.empty()) {
        int t = q.front();
        q.pop();
        int siz = G[t].size();
        for (int i = 0; i < siz; ++i) {
            edge &p = G[t][i];
            if (p.f && level[p.x] < 0) {
                level[p.x] = level[t] + 1;
                q.push(p.x);
            }
        }
    }
}
int dfs(int v, int f) {
    if (v == t) {
        return f;
    }
    int s = G[v].size();
    for (int &i = iter[v]; i < s; ++i) {
        edge &p = G[v][i];
        if (p.f && level[v] < level[p.x]) {
            int d = dfs(p.x, min(p.f, f));
            if (d) {
                p.f -= d;
                G[p.x][p.t].f += d;
                return d;
            }
        }
    }
    return 0;
}
int maxflow() {
    int flow = 0;
    while (1) {
        memset(level, -1, sizeof(level));
        bfs();
        if (level[t] == -1) {
            return flow;
        }
        memset(iter, 0, sizeof(iter));
        int f;
        while ((f = dfs(s, INF)) > 0) {
            flow += f;
        }
    }
}
int main() {
    int n;
    while (cin >> n) {
        for (int i = 1; i <= n; ++i) {
            cin >> r[i].a >> r[i].b;
        }
        for (int i = 1; i <= n; ++i) {
            cin >> b[i].a >> b[i].b;
        }
        s = 0, t = (n << 1) + 1;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (r[i].a < b[j].a && r[i].b < b[j].b) {
                    addedge(i, j + n, 1);
                }
            }
        }
        for (int i = 1; i <= n; ++i) {
            addedge(s, i, 1);
            addedge(i + n, t, 1);
        }
        printf("%d\n", maxflow());
        for (int i = 0; i <= 2 * n + 1; ++i) {
            G[i].clear();
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值