题解【CF277E Binary Tree on Plane】
Description
给你平面上 \(n\) 个点 \((2 \leq n \leq 400)\),要求用这些点组成一个二叉树(每个节点的儿子节点不超过两个),定义每条边的权值为两个点之间的欧几里得距离。求一个权值和最小的二叉树,并输出这个权值。
其中,点 \(i\) 可以成为点 \(j\) 的的父亲的条件是:点 \(i\) 的 \(y\) 坐标比 \(j\) 的 \(y\) 坐标大。
如果不存在满足条件的二叉树,输出 \(-1\) 。
Solution
边 \((a,b)\) 表示一条容量为 \(a\) ,费用为 \(b\) 的边
把每个点 \(u\) 拆成两个点入点 \(u_1\) 和出点 \(u_2\)
从源点向 \(u_1\) 连一条 \((2,0)\),意义为限制了 \(u\) 只能有两个儿子
从 \(u_2\) 向汇点连一条 \((1,0)\) ,意义是限制了 \(u\) 最多只有一个父亲
若 \(u_y > v_y\) 则在 \(u_1\) 和 \(v_2\) 之间连一条 \((1,Len)\),其中 Len 是两点之间的距离 \(\sqrt {(u_x - v_x)^2 + (u_y-v_y)^2}\)
然后跑最小费用最大流完事。
Code
#include <bits/stdc++.h>
#define db double
using namespace std;
const int N = 450;
const int INF = 1000000000;
int n, k, S, T, vis[N], cnt, f[N * 2], pre[N * 2];
db dis[N * 2];
struct edge {
int v, f; db w; edge *next, *rev;
}pool[N * N], *head[N * 2], *r[N * 2];
struct node {
int sid, tid;
db x, y;
}a[N];
inline db Len(db x1, db y1, db x2, db y2) {
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
inline void addedge(int u, int v, int f, db w) {
edge *p = &pool[++cnt], *q = &pool[++cnt];
p->v = v, p->f = f, p->w = w, p->next = head[u], head[u] = p; p->rev = q;
q->v = u, q->f = 0, q->w = -w, q->next = head[v], head[v] = q; q->rev = p;
}
inline bool spfa() {
for(int i = S; i <= T; i++) pre[i] = -1, dis[i] = INF, r[i] = NULL, vis[i] = 0;
queue <int> Q; Q.push(S), dis[S] = 0, vis[S] = 1; f[S] = INF;
while(!Q.empty()) {
int u = Q.front(), v; Q.pop(); vis[u] = 0;
for(edge *p = head[u]; p; p = p->next) {
if(p->f && dis[v = p->v] > dis[u] + p->w) {
dis[v] = dis[u] + p->w;
pre[v] = u, r[v] = p;
f[v] = min(f[u], p->f);
if(!vis[v]) vis[v] = 1, Q.push(v);
}
}
} return pre[T] != -1;
} int MF; db MC;
inline void MCMF() {
while(spfa()) {
for(int i = T; i != S; i = pre[i])
r[i]->f -= f[T], r[i]->rev->f += f[T];
MF += f[T], MC += 1.0 * dis[T] * f[T];
}
}
int main() {
scanf("%d", &n); S = 0, T = 2 * n + 1;
for(int i = 1; i <= n; i++) {
scanf("%lf %lf", &a[i].x, &a[i].y);
a[i].sid = i * 2 - 1, a[i].tid = i * 2;
addedge(S, a[i].sid, 2, 0);
addedge(a[i].tid, T, 1, 0);
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(i != j && a[i].y > a[j].y)
addedge(a[i].sid, a[j].tid, 1, Len(a[i].x, a[i].y, a[j].x, a[j].y));
MCMF();
if(MF == n - 1) printf("%lf\n", MC);
else printf("-1\n");
return 0;
}
题解【CF277E Binary Tree on Plane】的更多相关文章
- CF277E Binary Tree on Plane
CF277E Binary Tree on Plane 题目大意 给定平面上的 \(n\) 个点,定义两个点之间的距离为两点欧几里得距离,求最小二叉生成树. 题解 妙啊. 难点在于二叉的限制. 注意到 ...
- leetcode 题解:Binary Tree Inorder Traversal (二叉树的中序遍历)
题目: Given a binary tree, return the inorder traversal of its nodes' values. For example:Given binary ...
- [LeetCode 题解]: Flatten Binary Tree to Linked List
Given a binary tree, flatten it to a linked list in-place. For example,Given 1 / \ 2 5 / \ \ 3 4 6 T ...
- leetcode题解:Construct Binary Tree from Preorder and Inorder Traversal (根据前序和中序遍历构造二叉树)
题目: Given preorder and inorder traversal of a tree, construct the binary tree. Note:You may assume t ...
- CF 277E Binary Tree on Plane (拆点 + 费用流) (KM也可做)
题目大意: 平面上有n个点,两两不同.现在给出二叉树的定义,要求树边一定是从上指向下,即从y坐标大的点指向小的点,并且每个结点至多有两个儿子.现在让你求给出的这些点是否能构成一棵二叉树,如果能,使二叉 ...
- Codefoces 277 E. Binary Tree on Plane
题目链接:http://codeforces.com/problemset/problem/277/E 参考了这篇题解:http://blog.csdn.net/Sakai_Masato/articl ...
- LeetCode题解之Binary Tree Right Side View
1.题目描述 2.问题分析 使用层序遍历 3.代码 vector<int> v; vector<int> rightSideView(TreeNode* root) { if ...
- LeetCode题解之Binary Tree Pruning
1.题目描述 2.问题分析 使用递归 3.代码 TreeNode* pruneTree(TreeNode* root) { if (root == NULL) return NULL; prun(ro ...
- LeetCode题解Maximum Binary Tree
1.题目描述 2.分析 找出最大元素,然后分割数组调用. 3.代码 TreeNode* constructMaximumBinaryTree(vector<int>& nums) ...
随机推荐
- K8S-RedisCluster搭建
简介 Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接, mastart节点之间存放的数据并不是相同的,只是其中的一部分,当我们请 ...
- Python的sys.argv使用说明
刚开始使用这个参数的时候,很不明白其含义.网上搜索很多都是贴的官网上面的一则实例,说看懂,就明白.可是,我看不懂.现在在回头看这个参数使用,并不是很麻烦. 举几个小例子就明白了. 创建一个脚本,内容如 ...
- Halcon如何保存仿射变换矩阵
这里我们通过序列化来实现的,如下图,写到硬盘的HomMat2D_1内容和从硬盘里HomMat2D_2读出的内容一致,源代码在图片下方. Halcon源代码: hom_mat2d_identity (H ...
- Focalprice李培亮:梦想让人在我店里排队
[亿邦动力网讯]4月3日消息,外贸B2C平台Focalprice总裁李培亮日前亮相亿邦动力网联合河南省商务厅举办的“第九届中国中小企业电子商务大会暨2014中国(河南)跨境贸易电子商务峰会”,表达自己 ...
- PowerShell自定义修改远程桌面RDP端口
应朋友的要求写了一个通过PowerShell修改远程桌面(Remote Desktop)端口的脚本,不复杂,启动脚本后有两个选项:1.自定义远程桌面:2.回复远程桌面的默认端口3389 发出来给有用的 ...
- FPGA的软核与硬核
硬核 zynq和pynq系列的fpga都是双ARM/Cortex-A9构成,这里的ARM处理器为硬核,Cortex-A9部分为FPGA部分.即整体分为两部分:PS/PL.PS部分为A9处理器部分,PL ...
- 团队作业——王者光耀:team
光耀101 <光耀101>是福州大学数计学院计算机专业推出的中国首部程序猿脱发养成节目.由张栋担任发起人,刘晨瑶.畅畅担任导师. 该节目召集了你猜多少位选手,通过任务.训练.考核,让选 ...
- 《我是一只IT小小鸟》 读书笔记
<我是一只IT小小鸟>讲述了IT人员的成长经历,邀请了许多名IT行业的职员,学生,研究生写了自己的亲身经历和人生感悟,以书中可以看到我国IT行业的快速进步,以及看到IT员在这条道路上的坎坷 ...
- RovingUI组件库-包含堆栈式通知提醒框(Toast)的小程序组件库
RovingUI是个人在开发小程序过程中将用到的组件集合而成的一个UI库,包含一些基本通用组件(按钮.栅格.通用样式.徽标.通知和面包屑). 源起得归于我在开发中没有找到现成的堆栈式提醒框(比如ant ...
- lintcode-198-排列序号II
198-排列序号II 给出一个可能包含重复数字的排列,求这些数字的所有排列按字典序排序后该排列在其中的编号.编号从1开始. 样例 给出排列[1, 4, 2, 2],其编号为3. 思路 和 lintco ...