POJ3565 Ants(二分图最佳匹配)

川长思鸟来 2021-11-09 23:30 362阅读 0赞

题意:在坐标系中有N只蚂蚁,N棵苹果树,给你蚂蚁和苹果树的坐标。让每只蚂蚁去一棵苹果树,一棵苹果树对应一只蚂蚁。这样就有N条直线路线,问:怎样分配,才能使总路程和最小,且N条线不相交。

分析:不相交线段长度(取反)转化为最大匹配,详见《算法竞赛进阶指南》P427。

代码:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cmath>
  5. using namespace std;
  6. const int N = 105;
  7. int a[N], b[N], c[N], d[N];
  8. double w[N][N]; // 边权
  9. double la[N], lb[N]; // 左、右部点的顶标
  10. bool va[N], vb[N]; // 访问标记:是否在交错树中
  11. int match[N], ans[N]; // 右部点匹配了哪一个左部点
  12. int n;
  13. double upd[N], delta;
  14. bool dfs(int x) {
  15. va[x] = 1; // 访问标记:x在交错树中
  16. for (int y = 1; y <= n; y++)
  17. if (!vb[y])
  18. if (fabs(la[x] + lb[y] - w[x][y]) < 1e-8) { // 相等子图
  19. vb[y] = 1; // 访问标记:y在交错树中
  20. if (!match[y] || dfs(match[y])) {
  21. match[y] = x;
  22. return true;
  23. }
  24. }
  25. else upd[y] = min(upd[y], la[x] + lb[y] - w[x][y]);
  26. return false;
  27. }
  28. void KM() {
  29. for (int i = 1; i <= n; i++) {
  30. la[i] = -1e10; // -inf
  31. lb[i] = 0;
  32. for (int j = 1; j <= n; j++)
  33. la[i] = max(la[i], w[i][j]);
  34. }
  35. for (int i = 1; i <= n; i++)
  36. while (true) { // 直到左部点找到匹配
  37. memset(va, 0, sizeof(va));
  38. memset(vb, 0, sizeof(vb));
  39. delta = 1e10; // inf
  40. for (int j = 1; j <= n; j++) upd[j] = 1e10;
  41. if (dfs(i)) break;
  42. for (int j = 1; j <= n; j++)
  43. if (!vb[j]) delta = min(delta, upd[j]);
  44. for (int j = 1; j <= n; j++) { // 修改顶标
  45. if (va[j]) la[j] -= delta;
  46. if (vb[j]) lb[j] += delta;
  47. }
  48. }
  49. }
  50. int main()
  51. {
  52. cin >> n;
  53. for (int i = 1; i <= n; i++) scanf("%d%d", &a[i], &b[i]);
  54. for (int i = 1; i <= n; i++) scanf("%d%d", &c[i], &d[i]);
  55. for (int i = 1; i <= n; i++)
  56. for (int j = 1; j <= n; j++)
  57. w[i][j] = -sqrt((a[i]-c[j])*(a[i]-c[j])*1.0+(b[i]-d[j])*(b[i]-d[j])*1.0);
  58. KM();
  59. for (int i = 1; i <= n; i++) ans[match[i]] = i;
  60. for (int i = 1; i <= n; i++) printf("%d\n", ans[i]);
  61. return 0;
  62. }

发表评论

表情:
评论列表 (有 0 条评论,362人围观)

还没有评论,来说两句吧...

相关阅读

    相关 二分匹配

    Bi-partite graph ![20130902222653718][] 二分图的定义: 二分图是这样的一个图,它的顶点可以分为两个集合X和Y。所有的边关联

    相关 二分匹配

    今天看了很多博客!终于看懂了一点点,想记录一下! 首先你要知道什么是增广路径(虽然我现在还不明白![大哭][wail.gif])   这是一种用增广路求二分图最