NC244798. Binary Tree on Plane
描述
输入描述
第一行一个,表示节点个数。
之后行每行两个整数表示每个点的坐标。
输出描述
如果存在一个权值和最小的二叉树,输出这个最小的权值和(精度误差不超过。
如果不存在请输出。
示例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(); }