列表

详情


NC244798. Binary Tree on Plane

描述

给你平面上 n 个点 ,要求用这些点组成一个二叉树(每个节点的儿子节点不超过两个),定义每条边的权值为两个点之间的欧几里得距离。求一个权值和最小的二叉树,并输出这个权值。

其中,点 i 可以成为点 j 的的父亲的条件是:点 iy 坐标比 jy 坐标大。

输入描述

第一行一个,表示节点个数。

之后n行每行两个整数表示每个点的坐标。

输出描述

如果存在一个权值和最小的二叉树,输出这个最小的权值和(精度误差不超过

如果不存在请输出-1

示例1

输入:

3
0 0
1 0
2 1

输出:

3.650281539872885

示例2

输入:

4
0 0
1 0
2 1
2 0

输出:

-1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++ 11.0.1) 解法, 执行用时: 513ms, 内存消耗: 7352K, 提交时间: 2022-11-28 11:04:33

#include "bits/stdc++.h"

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

#define endl "\n"
#define pb push_back
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

const int INF = 0x3f3f3f3f;
// const ll mod = 998244353;
// const ll mod = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
const double R = 0.57721566490153286060651209;

const int maxn = 1005;      //点数

struct Edge {
    int from, to, cap, flow;
    double cost;

    Edge(int u, int v, int c, int f, double cc)
            : from(u), to(v), cap(c), flow(f), cost(cc) {}
};

struct MCMF {
    int n, m;
    vector<Edge> edges;
    vector<int> G[maxn];
    int inq[maxn];  //是否在队列中
    double d[maxn];    //bellmanford
    int p[maxn];    //上一条弧
    int a[maxn];    //可改进量
    void init(int n) {
        this->n = n;
        for (int i = 0; i <= n; ++i) G[i].clear();
        edges.clear();
    }

    void addEdge(int from, int to, int cap, double cost) {
        edges.emplace_back(Edge(from, to, cap, 0, cost));
        edges.emplace_back(Edge(to, from, 0, 0, -cost));
        m = int(edges.size());
        G[from].emplace_back(m - 2);
        G[to].emplace_back(m - 1);
    }

    bool spfa(int s, int t, int &flow, double &cost) {
        for (int i = 1; i <= n; ++i) d[i] = INF;
        memset(inq, 0, sizeof(inq));
        d[s] = 0;
        inq[s] = 1;
        p[s] = 0;
        queue<int> q;
        a[s] = INF;
        q.push(s);
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            inq[u] = 0;
            for (int i = 0; i < int(G[u].size()); ++i) {
                Edge &e = edges[G[u][i]];
                if (e.cap > e.flow && d[e.to] > d[u] + e.cost) {
                    d[e.to] = d[u] + e.cost;
                    p[e.to] = G[u][i];
                    a[e.to] = min(a[u], e.cap - e.flow);
                    if (!inq[e.to]) {
                        q.push(e.to);
                        inq[e.to] = 1;
                    }
                }
            }
        }
        if (d[t] == INF) return false;
        flow += a[t];
        cost += d[t] * a[t];
        for (int u = t; u != s; u = edges[p[u]].from) {
            edges[p[u]].flow += a[t];
            edges[p[u] ^ 1].flow -= a[t];
        }
        return true;
    }

    int MincostMaxflow(int s, int t, double &cost) {
        int flow = 0;
        cost = 0;
        while (spfa(s, t, flow, cost));
        return flow;
    }
} mcmf;

double Dis(pair<double, double> a, pair<double, double> b) {
    return sqrt(((a.first - b.first) * (a.first - b.first)) + (a.second - b.second) * (a.second - b.second));
}

bool cmp(pair<double, double> a, pair<double, double> b) {
    return a.second == b.second ? a.first < b.first : a.second > b.second;
}

void solve() {
    int n;
    scanf("%d",&n);
    mcmf.init(2 * n + 1);
    int s = 0, t = 2 * n + 1;
    pair<double, double> p[maxn];
    for(int i = 1;i <= n; i++) {
        scanf("%lf%lf",&p[i].first, &p[i].second);
        mcmf.addEdge(s, n + i, 2, 0); // 源点连接子节点
        mcmf.addEdge(i, t, 1, 0); // 根节点连接汇点
    }
    sort(p + 1, p + n + 1, cmp);
    if(p[1].second == p[2].second) { // 两个根结点?不存在的
        printf("-1\n");
        return ;
    }
    for(int i = 1;i <= n; i++) {
        for(int j = i + 1;j <= n; j++) {
            if(p[i].second == p[j].second) continue;
            mcmf.addEdge(n + i, j, 1, Dis(p[i], p[j]));
        }
    }
    double mincost;
    auto ans = mcmf.MincostMaxflow(s, t, mincost);
    if(ans == n - 1) printf("%.8lf\n",mincost);
    else printf("-1\n");
}

signed main() {
    solve();
}

上一题