传送门:http://arc076.contest.atcoder.jp/tasks/arc076_b

本题是一个图论问题——Manhattan距离最小生成树(MST)。

在一个平面网格上有n个格点,第i个格点的坐标是(xi,yi),构造一条连接点(a,b)和点(c,d)的边的代价是min{|a-c|,|b-d|}。对给定的n个格点构造连通图,使得总代价最小。

这是一个最小生成树(MST)问题。最“简单”的方法是,由n个结点构造一个无向完全图Kn,之后用Prim算法生成MST。这个程序的时间复杂度为O(n2logn),空间复杂度为O(n2)。对于105的数据规模,这个方法显然是不可取的。

考虑到Kruskal算法和Prim算法的时间复杂度均为O(ElogV),应尽可能地降低E的数量级(从Θ(n2)降至Θ(n))。

考虑以下的构造方式:对于点(a,b)和点(c,d),不构造代价为min{|a-c|,|b-d|}的边,而是构造两条边,其中一条边的代价为|a-c|,另一条边的代价为|b-d|。设存在i,j,k,使得xi<xj<xk,则连接ik的代价为|xi-xk|的边一定不会出现在MST中。因此,只需在坐标上相邻的两个结点之间构造边即可。这个构造方式构造的边数E=2(n-1),是Θ(n)的。具体的构造方式如下:

a.对结点按x坐标排序,在每一对相邻的点之间构造一条边,代价是相邻两点距离的x分量;

b.对结点按y坐标排序,在每一对相邻的点之间构造一条边,代价是相邻两点距离的y分量;

构造边的时间复杂度为O(nlogn),空间复杂度为O(n)。

之后,用Kruskal算法生成MST,时间复杂度为O(nlogn)。参考程序如下:

#include <bits/stdc++.h>
using namespace std; #define MAX_N 100010 struct point {int id, x, y;};
struct edge {int u, v, w;}; int n;
point p[MAX_N];
edge edgeset[ * MAX_N]; //disjoint set
int pa[MAX_N];
int rnk[MAX_N]; void init(void)
{
memset(pa, , sizeof(pa));
memset(rnk, , sizeof(rnk));
for (int i = ; i < n; i++) {
pa[i] = i;
rnk[i] = ;
}
} int find(int x)
{
if (pa[x] == x) return x;
else return pa[x] = find(pa[x]);
} void unite(int x, int y)
{
x = find(x);
y = find(y);
if (x == y) return;
if (rnk[x] < rnk[y]) pa[x] = y;
else {
pa[y] = x;
if (rnk[x] == rnk[y]) rnk[x]++;
}
} bool same(int x, int y)
{
return (find(x) == find(y));
} int abs(int a)
{
return a >= ? a: -a;
} bool cmp_x(point a, point b)
{
return a.x < b.x;
} bool cmp_y(point a, point b)
{
return a.y < b.y;
} bool cmp_edge(edge a, edge b)
{
return a.w < b.w;
} //kruskal minimum spanning tree
int mst(void)
{
init();
int res = ;
for (int i = ; i < * (n - ); i++) {
edge e = edgeset[i];
if (!same(e.u, e.v)) {
unite(e.u ,e.v);
res += e.w;
}
}
return res;
} int main(void)
{
scanf("%d", &n);
for (int i = ; i < n; i++) {
scanf("%d%d", &p[i].x, &p[i].y);
p[i].id = i;
}
sort(p, p + n, cmp_x);
for (int i = ; i < n - ; i++) {
edgeset[i].u = p[i].id;
edgeset[i].v = p[i + ].id;
edgeset[i].w = abs(p[i + ].x - p[i].x);
}
sort(p, p + n, cmp_y);
for (int i = ; i < n - ; i++) {
edgeset[i + n - ].u = p[i].id;
edgeset[i + n - ].v = p[i + ].id;
edgeset[i + n - ].w = abs(p[i + ].y - p[i].y);
}
sort(edgeset, edgeset + * (n - ), cmp_edge);
printf("%d\n", mst());
return ;
}

AtCoder ARC 076D - Built?的更多相关文章

  1. 【题解】Atcoder ARC#90 F-Number of Digits

    Atcoder刷不动的每日一题... 首先注意到一个事实:随着 \(l, r\) 的增大,\(f(r) - f(l)\) 会越来越小.考虑暴力处理出小数据的情况,我们可以发现对于左端点 \(f(l) ...

  2. AtCoder ARC 076E - Connected?

    传送门:http://arc076.contest.atcoder.jp/tasks/arc076_c 平面上有一个R×C的网格,格点上可能写有数字1~N,每个数字出现两次.现在用一条曲线将一对相同的 ...

  3. AtCoder ARC 082E - ConvexScore

    传送门:http://arc082.contest.atcoder.jp/tasks/arc082_c 本题是一个平面几何问题. 在平面直角坐标系中有一个n元点集U={Ai(xi,yi)|1≤i≤n} ...

  4. Atcoder ARC 082C/D

    C - Together 传送门:http://arc082.contest.atcoder.jp/tasks/arc082_a 本题是一个数学问题. 有一个长度为n的自然数列a[1..n],对于每一 ...

  5. AtCoder ABC 076D - AtCoder Express

    传送门:http://abc076.contest.atcoder.jp/tasks/abc076_d 本题是一个运动学问题——匀变速运动. 一个质点,从静止开始运动.按照速度限制,可将运动划分成n个 ...

  6. 【题解】 AtCoder ARC 076 F - Exhausted? (霍尔定理+线段树)

    题面 题目大意: 给你\(m\)张椅子,排成一行,告诉你\(n\)个人,每个人可以坐的座位为\([1,l]\bigcup[r,m]\),为了让所有人坐下,问至少还要加多少张椅子. Solution: ...

  7. 【题解】Atcoder ARC#96 F-Sweet Alchemy

    首先,我们发现每一个节点所选择的次数不好直接算,因为要求一个节点被选择的次数大于等于父亲被选择的次数,且又要小于等于父亲被选择的次数 \(+D\).既然如此,考虑一棵差分的树,规定每一个节点被选择的次 ...

  8. AtCoder ARC 090 E / AtCoder 3883: Avoiding Collision

    题目传送门:ARC090E. 题意简述: 给定一张有 \(N\) 个点 \(M\) 条边的无向图.每条边有相应的边权,边权是正整数. 小 A 要从结点 \(S\) 走到结点 \(T\) ,而小 B 则 ...

  9. 【题解】Atcoder ARC#67 F-Yakiniku Restaurants

    觉得我的解法好简单,好优美啊QAQ 首先想想暴力怎么办.暴力的话,我们就枚举左右端点,然后显然每张购物券都取最大的值.这样的复杂度是 \(O(n ^{2} m)\) 的.但是这样明显能够感觉到我们重复 ...

随机推荐

  1. Android 实现文字与图片的混排

    在我们的项目中,常常会碰到图片与文字混排的问题.解决这类问题的方法有非常多,本文给出的方法不是唯一的.仅仅有依据实际场景才干找到更适合的方法. 本文主要通过xml布局来实现图片与文字的混排(水平排列) ...

  2. Xcode HeaderDoc 教程(3)

    打开 MathAPI.h,将第一个 @param 标签的參数名由firstNumber 改动为 thirdNumber,然后编译. 有一个警告发生.甚至提出了改动建议.它不会影响不论什么事情,但有助于 ...

  3. luogu3358 最长k可重区间集问题 网络流

    题目大意: 关键词:最小费用最大流 不相交路径 如果两个线段重叠了,那我们则把一个线段放在下一层,另一个线段放在上一层.把流量为1的流看作一条线,一条线把位于同一层的线段(互不重叠)都串了起来.最多有 ...

  4. 弹出框中选项卡的运用(easyUI)

    先看一下页面效果: 此处有两个知识点:一个是弹出框的运用,一个是选项卡的运用 分析一下该HTML代码,最外面一个div是弹出框的,默认是关闭状态,可通过ID来控制弹出框的开关,该div的样式是easy ...

  5. Android Back键和Home键的区别

    back键 Android的程序无需刻意的去退出,当你一按下手机的back键的时候,系统会默认调用程序栈中最上层Activity的Destroy()方法来,销毁当前Activity.当此Activit ...

  6. Stick ------ 剪枝神题

    这个是自己剪得 , 我感觉已经很不错了  但是不知道哪里出了问题  一直  超时 // 根据所给答案 和 题目要求 最直观的就可以有剪枝的地方 而且 剪枝剪得越早 就越省时省力 // 好的思路也可以省 ...

  7. C - Gravity Flip

    Problem description Little Chris is bored during his physics lessons (too easy), so he has built a t ...

  8. javascript 核心概念(1)-数据类型

    语法 (1)到现在为止,大多数浏览器也还是支持到ECMAScript 第三版的标准. 核心概念就是一个语言的基本工作原理,涉及语法,操作符,数据类型. (2)javascript的一切--变量,函数名 ...

  9. 《Linux程序设计》笔记(二)shell程序设计

    1. 进程树形显示 ps -e f 2. 重定向 > 覆盖文件 >> 附加至文件 1> 标准输出 2> 标准错误输出 0 代表一个程序的标准输入 3. 程序可以在当前目录 ...

  10. ROS:使用ubuntuKylin17.04安装ROS赤xi龟

    使用ubuntuKylin17.04安装 参考了此篇文章:SLAM: Ubuntu16.04安装ROS-kinetic 重复官方链接的步骤也没有成功. 此后发现4.10的内核,不能使用Kinetic. ...