• POJ3565 Ants 空间点对不相交匹配最小权值匹配


    题意:给定平面上两类同样多的点,要求输出一种方案使得所有匹配的点的连线两两不相交。

    解法:考虑到下面的一般情况:

    可以很容易的证明两条交叉边的距离和一定大于两条不交叉的距离和,因此问题转化为只要原图中存在交叉边,那么就可以找到更小的匹配的方式使得总距离更小。使用KM算法求出最小权值匹配输出匹配方案即可。

    代码如下:

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    using namespace std;
    
    int N;
    double w[105][105];
    int sx[105], sy[105];
    double lx[105], ly[105];
    double slack[105];
    int match[105];
    
    struct Node {
        int x, y;    
    }c[105], t[105];
    
    double dist(const Node &a, const Node &b) {
        return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
    }
    
    void build() {
        for (int i = 1; i <= N; ++i) {
            for (int j = 1; j <= N; ++j) {
                w[i][j] = -dist(c[i], t[j]);
            }
        }
    }
    
    int path(int u) {
        sx[u] = 1;
        for (int i = 1; i <= N; ++i) {
            if (sy[i]) continue;
            double t = lx[u] + ly[i] - w[u][i];
            if (fabs(t) < 1e-6) { // 如果这个值等于0 
                sy[i] = 1;
                if (!match[i] || path(match[i])) {
                    match[i] = u;
                    return true;    
                }
            } else {
                slack[i] = min(slack[i], t);
            }
        }
        return false;
    }
    
    void KM() {
        memset(match, 0, sizeof (match));
        fill(ly, ly+105, 0);
        fill(lx, lx+105, 0);
        for (int i = 1; i <= N; ++i) {
            for (int j = 1; j <= N; ++j) { // 为i选择一个最大的权值 
                lx[i] = max(lx[i], w[i][j]);
            }
        }
        for (int i = 1; i <= N; ++i) { // 每一次都要为i找到一条增广路
            fill(slack, slack+105, 1e30);
            while (1) {
                memset(sx, 0, sizeof (sx));
                memset(sy, 0, sizeof (sy));
                if (path(i)) break;
                double d = 1e30;
                for (int j = 1; j <= N; ++j) {
                    if (!sy[j])    d = min(d, slack[j]);
                }
                for (int j = 1; j <= N; ++j) {
                    if (sx[j]) lx[j] -= d;
                    if (sy[j]) ly[j] += d;
                    else slack[j] -= d;
                }
            }
        }
        for (int i = 1; i <= N; ++i) {
            for (int j = 1; j <= N; ++j) {
                if (match[j] == i) {
                    printf("%d\n", j);
                    break;
                }
            }
        }
    }
    
    int main() {
        while (scanf("%d", &N) != EOF) {
            for (int i = 1; i <= N; ++i)    {
                scanf("%d %d", &c[i].x, &c[i].y);
            }
            for (int i = 1; i <= N; ++i)    {
                scanf("%d %d", &t[i].x, &t[i].y);
            }
            build();
            KM();
        }
        return 0;    
    }
  • 相关阅读:
    使用Spring提供的缓存抽象机制整合EHCache为项目提供二级缓存
    Spring使用Cache、整合Ehcache(转)
    每天学习SQL
    多线程
    ### The error may involve defaultParameterMap ### The error occurred while setting parameters
    日志分表
    Quartz学习(转)
    Quartz中时间表达式的设置-----corn表达式 (转)(http://www.cnblogs.com/GarfieldTom/p/3746290.html)
    分享一个测试图片的方式
    阿里云ECS配置踩坑之路
  • 原文地址:https://www.cnblogs.com/Lyush/p/3024244.html
Copyright © 2020-2023  润新知