• POJ 3565 Ants (最小权匹配)


    题意

    给出一些蚂蚁的点,给出一些树的点,两两对应,使他们的连线不相交,输出一种方案。

    思路

    一开始没想到怎么用最小权匹配……后来发现是因为最小权匹配的方案一定不相交(三角形两边之和大于第三边)……还是too young too simple……没有融会贯通……

    代码

      [cpp] #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <algorithm> #include <string> #include <cstring> #define MID(x,y) ((x+y)/2) #define MEM(a,b) memset(a,b,sizeof(a)) #define REP(i, begin, m) for (int i = begin; i < begin+m; i ++) using namespace std; const int MAXV = 205; //X or Y点集大小 const int oo = 0x3fffffff; const double eps = 1e-8; template <class weight_type> struct MaximalMatchingOfWeightedBipartiteGraph{ weight_type w[MAXV][MAXV]; //权值 int sv, tv; //Perfect Matching, sv should equal to tv bool S[MAXV], T[MAXV]; weight_type lx[MAXV], ly[MAXV]; //X、Y点集可行顶标 int left[MAXV]; weight_type slack[MAXV]; void init(int v){ sv = tv = v; MEM(w, 0); } void add_uedge(int u, int v, weight_type _w){ w[u][v] = _w; } bool cross_path(int u){ S[u] = true; for (int v = 1; v <= tv; v ++){ if(T[v]) continue; weight_type t = lx[u] + ly[v] - w[u][v]; if (t < eps){ T[v] = true; if (left[v] == 0 || cross_path(left[v])){ left[v] = u; return true; } } else{ slack[v] = min(slack[v], t); } } return false; } weight_type solve(){ //Init MEM(left, 0); for (int i = 1; i <= sv; i ++){ lx[i] = 0; ly[i] = 0; for (int j = 1; j <= tv; j ++) lx[i] = max(lx[i], w[i][j]); } //Main for (int i = 1; i <= sv; i ++){ for (int j = 1; j <= tv; j ++) slack[j] = oo; while(1){ MEM(S, false); MEM(T, false); if (cross_path(i)){ break; } else{ weight_type d = oo; for (int j = 1; j <= tv; j ++) if (!T[j]) d = min(d, slack[j]); for (int j = 1; j <= sv; j ++) if (S[j]) lx[j] -= d; for (int j = 1; j <= tv; j ++){ if (T[j]) ly[j] += d; else slack[j] -= d; //匈牙利树中T集点ly不变,S集点lx减小,更新slack值 } } } } weight_type res = 0; for(int i = 1; i <= sv; i ++) res += lx[i]; for(int i = 1; i <= tv; i ++) res += ly[i]; return res; } }; MaximalMatchingOfWeightedBipartiteGraph <double> km; struct Point{ double x, y; }p[MAXV]; double dist(int i, int j){ return sqrt((p[i].x - p[j].x)*(p[i].x - p[j].x) + (p[i].y - p[j].y)*(p[i].y - p[j].y)); } int main(){ //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); int n; while(scanf("%d", &n) != EOF){ REP(i, 1, n){ scanf("%lf %lf", &p[i+n].x, &p[i+n].y); } REP(i, 1, n){ scanf("%lf %lf", &p[i].x, &p[i].y); } km.init(n); REP(i, 1, n){ REP(j, 1, n){ km.add_uedge(i, j, -dist(i, j+n)); } } //printf("%f ", -km.solve()); km.solve(); REP(i, 1, n){ printf("%d ", km.left[i]); } } return 0; } [/cpp]
  • 相关阅读:
    慕课网-安卓工程师初养成-3-2 Java中的算术运算符
    慕课网-安卓工程师初养成-3-1 什么是运算符
    慕课网-安卓工程师初养成-2-13 练习题
    慕课网-安卓工程师初养成-2-12 如何在Java中使用注释
    慕课网-安卓工程师初养成-2-11 Java常量
    慕课网-安卓工程师初养成-2-10 Java中的强制类型转换
    试把一个正整数n拆分为若干个
    求解两个给定正整数m、n的最大公约数(m、n)
    统计n!尾部零
    横竖折对称方阵
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114085.html
Copyright © 2020-2023  润新知