CF277E Binary Tree on Plane

题目大意

给定平面上的 \(n\) 个点,定义两个点之间的距离为两点欧几里得距离,求最小二叉生成树。

题解

妙啊。

难点在于二叉的限制。

注意到二叉树每一个点最多有一个父亲,最多可以有两个儿子,这让我们联想到了网络流中的容量。

考虑建图:

令源点为 \(s\),汇点为 \(t\)。

我们将每一个点 \(u\) 拆为两个点 \(u_1,u_2\);

每个点最多可以有两个儿子 \(\Rightarrow\) 从 \(s\) 向 \(u_1\) 连一条容量为 \(2\),费用为 \(0\) 的边。

每个点最多可以有一个父亲 \(\Rightarrow\) 从 \(u_2\) 向 \(t\) 连一条容量为 \(1\),费用为 \(0\) 的边。

\(u\) 可以成为 \(v\) 的父亲 \(\Rightarrow\) 从 \(u_1\) 向 \(v_2\) 连一条容量为 \(1\),费用为 \(\operatorname{dist}(u,v)\) 的边。

然后我们跑最小费用最大流,判断最大流是否为 \(n-1\) 即可。

/*---Author:HenryHuang---*/
#include<bits/stdc++.h>
#define eps 1e-6
using namespace std;
const int maxn=800+5;
typedef long long ll;
struct edge{
int to,nex,w;
double v;
}e[maxn*maxn*2];
int head[maxn],cur[maxn],tot=1;
void add(int a,int b,int c,double d){
e[++tot]=(edge){b,head[a],c,d};
head[a]=cur[a]=tot;
}
void addedge(int a,int b,int c,double d){
add(a,b,c,d);
add(b,a,0,-d);
}
int n,m,s,t;
double dis[maxn];
bool vis[maxn];
bool spfa(){
memset(vis,0,sizeof vis);
for(int i=s;i<=t;++i) vis[i]=0,dis[i]=(1ll<<60),cur[i]=head[i];
queue<int> Q;
dis[s]=0;vis[s]=1;Q.push(s);
while(!Q.empty()){
int u=Q.front();Q.pop();
vis[u]=0;
for(int i=head[u];i;i=e[i].nex){
int v=e[i].to;
if(e[i].w&&dis[v]-dis[u]-e[i].v>eps){
dis[v]=dis[u]+e[i].v;
if(!vis[v]) vis[v]=1,Q.push(v);
}
}
}
return dis[t]<(double)(1ll<<60);
}
int dfs(int u,int in){
if(u==t) return in;
int out=0,tmp;
vis[u]=1;
for(int i=cur[u];i;i=e[i].nex){
int v=e[i].to;cur[u]=i;
if((!vis[v])&&e[i].w&&abs(dis[v]-dis[u]-e[i].v)<eps&&(tmp=dfs(v,min(in,e[i].w)))){
e[i].w-=tmp,e[i^1].w+=tmp;
in-=tmp,out+=tmp;
if(!in) break;
}
}
if(!out) dis[u]=0;
vis[u]=0;
return out;
}
double x[maxn],y[maxn];
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;++i) cin>>x[i]>>y[i];
s=0,t=2*n+1;
for(int i=1;i<=n;++i) addedge(s,i,2,0),addedge(i+n,t,1,0);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
if(i!=j&&y[i]>y[j]) addedge(i,j+n,1,sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])));
int ans1=0;double ans2=0;
while(spfa()){
int tmp=dfs(s,2e9);
ans2+=dis[t]*tmp;
ans1+=tmp;
}
if(ans1==n-1) cout<<setprecision(6)<<fixed<<ans2<<'\n';
else cout<<-1<<'\n';
return 0;
}

CF277E Binary Tree on Plane的更多相关文章

  1. 题解【CF277E Binary Tree on Plane】

    Description 给你平面上 \(n\) 个点 \((2 \leq n \leq 400)\),要求用这些点组成一个二叉树(每个节点的儿子节点不超过两个),定义每条边的权值为两个点之间的欧几里得 ...

  2. CF 277E Binary Tree on Plane (拆点 + 费用流) (KM也可做)

    题目大意: 平面上有n个点,两两不同.现在给出二叉树的定义,要求树边一定是从上指向下,即从y坐标大的点指向小的点,并且每个结点至多有两个儿子.现在让你求给出的这些点是否能构成一棵二叉树,如果能,使二叉 ...

  3. Codefoces 277 E. Binary Tree on Plane

    题目链接:http://codeforces.com/problemset/problem/277/E 参考了这篇题解:http://blog.csdn.net/Sakai_Masato/articl ...

  4. [LintCode] Invert Binary Tree 翻转二叉树

    Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. ...

  5. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法

    二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...

  6. Leetcode 笔记 110 - Balanced Binary Tree

    题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...

  7. Leetcode, construct binary tree from inorder and post order traversal

    Sept. 13, 2015 Spent more than a few hours to work on the leetcode problem, and my favorite blogs ab ...

  8. [LeetCode] Find Leaves of Binary Tree 找二叉树的叶节点

    Given a binary tree, find all leaves and then remove those leaves. Then repeat the previous steps un ...

  9. [LeetCode] Verify Preorder Serialization of a Binary Tree 验证二叉树的先序序列化

    One way to serialize a binary tree is to use pre-oder traversal. When we encounter a non-null node, ...

随机推荐

  1. Epicor Advanced Unit of Measure

    作为先进的ERP系统,Epicor 不断发展以解决业务问题.2020 年 10 月,Epicor ERP 10.2.700 的一项强大的新功能高级计量单位 (UoM) 已投入生产. 发行说明看似简单, ...

  2. 在Go语言项目中使用Zap日志库

    在Go语言项目中使用Zap日志库 本文先介绍了Go语言原生的日志库的使用,然后详细介绍了非常流行的Uber开源的zap日志库,同时介绍了如何搭配Lumberjack实现日志的切割和归档. 在Go语言项 ...

  3. Deep Learning部署TVM Golang运行时Runtime

    Deep Learning部署TVM Golang运行时Runtime 介绍 TVM是一个开放式深度学习编译器堆栈,用于编译从不同框架到CPU,GPU或专用加速器的各种深度学习模型.TVM支持来自Te ...

  4. kali2020.4中安装nessus 8.14.0

    1.下载软件包 官网下载地址:https://www.tenable.com/downloads/nessus 2.安装nessus dpkg -i /root/Nessus-8.14.0-debia ...

  5. 重新整理 .net core 实践篇—————中间件[十九]

    前言 简单介绍一下.net core的中间件. 正文 官方文档已经给出了中间件的概念图: 和其密切相关的是下面这两个东西: IApplicationBuilder 和 RequestDelegate( ...

  6. 给小米路由R1D增加WebDAV服务

    我的R1D是14年买的,原装的硬盘已经不能用了,换了一块从笔记本上退役下来的500G硬盘后继续愉快的使用了-- 当初买这款路由器的原因之一是看中了它的内置硬盘,可以用来备份手机相册.存储智能摄像机录像 ...

  7. Vue.js源码解析-Vue初始化流程

    目录 前言 1. 初始化流程概述图.代码流程图 1.1 初始化流程概述 1.2 初始化代码执行流程图 2. 初始化相关代码分析 2.1 initGlobalAPI(Vue) 初始化Vue的全局静态AP ...

  8. 实验8、31个最重要的Python Flask面试问题和答案

    实验介绍 1. 实验内容 内容涵盖了31个最热门的Flask面试问题,帮助学生更好的理解Flask. 2. 实验要点 了解面试Flask开发人员的常见问题 实验内容 Flask面试问答 Q:Flask ...

  9. 【模拟7.22】visit(卢卡斯定理&&中国剩余定理)

    如此显然的组合数我把它当DP做,我真是.... 因为起点终点已经确定,我们发现如果我们确定了一个方向的步数其他方向也就确定了 组合数做法1: 设向右走了a步,然后向左走了b=a-n步,设向上为c,向下 ...

  10. EasyExcel随笔

    EasyExcel 注意点 不支持的功能 单个文件的并发写入.读取 读取图片 宏 csv读取 出现 NoSuchMethodException, ClassNotFoundException, NoC ...