UVALive 4043 Ants(最大权匹配)
2016-05-14 03:32
423 查看
题目链接:
UVALive 4043 Ants
题意:
给出平面上n个白点和n个黑点的点坐标,将这n个白点和n个黑点用n条不相交的线段连接,输出每个白点连接的黑点的编号.
n<=100.
分析:
假设有两个白点a1,a2和两个黑点b1,b2,且当前匹配为a1-b1,a2-b2.如果线段a1-b1和线段a2-b2相交,
可以得到距离关系dis(a1, b1) + dis(a2, b2) > dis(a1, b2) + dis(a2, b1).所以最佳的匹配是距离和短的匹配.
将白点和黑点建边,权值为距离的负数(求最小权匹配),然后用KM()求一下最大权匹配就好了.
UVALive 4043 Ants
题意:
给出平面上n个白点和n个黑点的点坐标,将这n个白点和n个黑点用n条不相交的线段连接,输出每个白点连接的黑点的编号.
n<=100.
分析:
假设有两个白点a1,a2和两个黑点b1,b2,且当前匹配为a1-b1,a2-b2.如果线段a1-b1和线段a2-b2相交,
可以得到距离关系dis(a1, b1) + dis(a2, b2) > dis(a1, b2) + dis(a2, b1).所以最佳的匹配是距离和短的匹配.
将白点和黑点建边,权值为距离的负数(求最小权匹配),然后用KM()求一下最大权匹配就好了.
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <climits> #include <cmath> #include <ctime> #include <cassert> #include <iomanip> #define IOS ios_base::sync_with_stdio(0); cin.tie(0); using namespace std; typedef long long ll; const int MAX_N = 1010; const double eps = 1e-8; const double DOUBLE_MAX = 1e9; const double DOUBLE_MIN = -1e9; int n, m, total; int head[MAX_N], matchx[MAX_N], matchy[MAX_N], visx[MAX_N], visy[MAX_N]; double lx[MAX_N], ly[MAX_N], w[MAX_N][MAX_N], slack[MAX_N]; struct Point{ double x, y; }white[MAX_N], black[MAX_N]; bool dfs(int x) { visx[x] = 1; for(int y = 0; y < m; y++){ if(visy[y]) continue; double tmp = lx[x] + ly[y] - w[x][y]; if(fabs(tmp) <= eps){ visy[y] = 1; if(matchy[y] == -1 || dfs(matchy[y])){ matchx[x] = y; matchy[y] = x; return true; } }else { slack[y] = min(slack[y], tmp); } } return false; } void KM() { memset(matchy, -1, sizeof(matchy)); memset(ly, 0, sizeof(ly)); for(int i = 0; i < n; i++){ lx[i] = DOUBLE_MIN; for(int j = 0; j < m; j++){ lx[i] = max(lx[i], w[i][j]); } } for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++) { slack[j] = DOUBLE_MAX; } while(1){ memset(visx, 0, sizeof(visx)); memset(visy, 0, sizeof(visy)); if(dfs(i)) break; double d = DOUBLE_MAX; for(int j = 0; j < m; j++){ if(!visy[j]) d = min(d, slack[j]); } for(int j = 0; j < n; j++) { if(visx[j]) lx[j] -= d; } for(int j = 0; j < m; j++){ if(visy[j]) ly[j] += d; else slack[j] -= d; } } } } int main() { IOS; int first = 1; while(cin >> n){ if(first) first = 0; else cout << endl; m = n; for(int i = 0; i < n; i++){ cin >> white[i].x >> white[i].y; } for(int i = 0; i < n; i++){ cin >> black[i].x >> black[i].y; } for(int i = 0;i < n; i++){ for(int j = 0; j < n; j++){ w[i][j] = - hypot(white[i].x - black[j].x, white[i].y - black[j].y); //cout << fixed << setprecision(6) << w[i][j] << endl; } } KM(); for(int i = 0; i < n; i++){ cout << matchx[i] + 1 << endl; } } return 0; }
相关文章推荐
- UVALive 3415 Guardian of Decency(最大独立集)
- UVALive 11419 SAM I AM (最小点覆盖输出)
- UVALive 11383 - Golden Tiger Claw(最小权匹配)
- 项目构建maven——maven的安装
- mininet实战2
- Floodlight安装指南
- 人像摄影技巧——镜头差异可改变脸部印象
- HDU 4619 Warm up 2(最大独立集)
- XML系列:(7)XML解析-Dom4j的DOM解析方式更新XML
- 爬虫闯关之旅-2
- 【JAVA】二 JAVA reference
- XML系列:(6)XML解析-Dom4j的DOM解析方式读取XML
- 7的倍数和末尾含7的数
- Best Practice: SharedPreferences
- 全局变量的特殊作用
- MATLAB和VS混合编程
- Codeforces Round #352 (Div. 2) (A-E)
- Java Socket多个客户端与服务器通信
- 完美乘积
- vector的使用