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\n", -km.solve()); km.solve(); REP(i, 1, n){ printf("%d\n", km.left[i]); } } return 0; } [/cpp]

你可能感兴趣的:(ant)