http://www.lydsy.com/JudgeOnline/problem.php?id=3051

http://uoj.ac/problem/57

这道题需要平面图转对偶图,点定位,最小生成树上的倍增(NOIP2013货车运输)3个步骤。

最后一个很简单了,前两个比较麻烦。。

点定位可以用玄学的梯形剖分(并不会orz),但这里可以离线用扫描线,类似圆的异或并那道题。

平面图转对偶图要把一条边拆成两条有向边,把每条有向边<u,v>找出和它夹角最小的<v,x>,这个过程要。。。。。。。。

算了不说了,网上的题解比我说得绝对要好得多,他们的题解也十分清晰:vfk的题解ydc的题解zky学长的题解

这道题细节巨多,我在set的重载运算符上坑了好久,还有set的判重机制。

据yveh说:在set里判断\(A=B\)为真要满足\(A<B\)为假且\(B<A\)为假。

一开始没注意这个,只是比较和横坐标全局变量的交点的高低,结果扫描线扫到一个点时先加进去了一些从这个点出发的向量,后来扫到进入这个点的向量时把从这个点出发的向量删除了QAQ。最后把删除和插入分开写了,惨啊。。。

代码有272行,好长啊。。

好久没写这么长的代码了。。

或者说从来没写过这么长的代码。。。。。

#include<set>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100003;
typedef long long ll;
int in() {
int k = 0, fh = 1; char c = getchar();
for(; c < '0' || c > '9'; c = getchar())
if (c == '-') fh = -1;
for(; c >= '0' && c <= '9'; c = getchar())
k = k * 10 + c - 48;
return k * fh;
} int n, M, Areanum; struct Point {
int x, y;
Point(int _x = 0, int _y = 0)
: x(_x), y(_y) {}
Point operator + (const Point &A) const {
return Point(x + A.x, y + A.y);
}
Point operator - (const Point &A) const {
return Point(x - A.x, y - A.y);
}
} P[N * 3]; int tot = 0; namespace INIT {
struct node {int nxt, to, h, from;} E[N << 1];
int cnt = 1, nt[N << 1], mark[N << 1], st[N << 1], point[N]; struct data {
int id; double num;
data(int _id = 0, double _num = 0) : id(_id), num(_num) {}
bool operator < (const data &A) const {
return num < A.num;
}
} D[N]; void ins(int u, int v, int w) {E[++cnt] = (node) {point[u], v, w, u}; point[u] = cnt;} ll Cross(int a, int b) {
return (ll) P[a].x * P[b].y - (ll) P[a].y * P[b].x;
} void init() {
int m, top, tmp, from;
ll Cro;
for (int i = 1; i <= n; ++i) {
m = 0;
for (int j = point[i]; j; j = E[j].nxt)
D[++m] = data(j, atan2(double(P[E[j].to].y - P[i].y), double(P[E[j].to].x - P[i].x)));
stable_sort(D + 1, D + m + 1);
for (int j = 1; j < m; ++j)
nt[D[j].id] = D[j + 1].id;
nt[D[m].id] = D[1].id; // printf("---PointID = %d---m = %d---\n", i, m);
// for(int j = 1; j <= m; ++j) printf("%d ", E[D[j].id].to);
// puts("");
} m = 0;
for (int i = 2; i <= cnt; ++i)
if (!mark[i]) {
from = E[i].from;
top = 1;
st[1] = i;
Cro = Cross(from, E[i].to);
tmp = nt[i ^ 1];
while (E[tmp].to != from) {
st[++top] = tmp;
Cro += Cross(E[tmp].from, E[tmp].to);
tmp = nt[tmp ^ 1];
}
Cro += Cross(E[tmp].from, from); if (Cro > 0) {
mark[tmp] = -1;
while (top) mark[st[top--]] = -1;
} else {
mark[tmp] = ++m;
while (top) mark[st[top--]] = m;
}
} // for (int i = 2; i <= cnt; ++i)
// printf("%d ---> %d RightSide : %d\n", E[i].from, E[i].to, mark[i]); Areanum = m;
}
} namespace MST {
struct Ed {
int u, v, w;
bool operator < (const Ed &A) const {
return w < A.w;
}
} EDGE[N << 1];
struct node {int nxt, to, w;} E[N << 1];
int tot2 = 0, cnt = 0, deep[N], f[N][18], c[N][18], point[N], fa[N]; void add(int u, int v, int w) {
EDGE[++tot2] = (Ed) {u, v, w};
// printf("%d <===dis = %d===> %d\n", u, w, v);
}
void ins(int u, int v, int w) {E[++cnt] = (node) {point[u], v, w}; point[u] = cnt;} int find(int x) {return fa[x] == x ? x : fa[x] = find(fa[x]);} void dfs(int x) {
for (int i = point[x]; i; i = E[i].nxt)
if (E[i].to != f[x][0]) {
f[E[i].to][0] = x;// printf("%d --fadis = %d--> %d\n", E[i].to, E[i].w, x);
c[E[i].to][0] = E[i].w;
deep[E[i].to] = deep[x] + 1;
dfs(E[i].to);
}
} void init() {
stable_sort(EDGE + 1, EDGE + tot2 + 1);
for (int i = 1; i <= Areanum; ++i)
fa[i] = i; int x, y, fx, fy, con = 0;
for (int i = 1; i <= tot2; ++i) {
x = EDGE[i].u; y = EDGE[i].v;
fx = find(x); fy = find(y);
if (fx != fy) {
++con;
if (con == Areanum) break;
fa[fx] = fy;
ins(x, y, EDGE[i].w);
ins(y, x, EDGE[i].w);
}
} for (int i = 1; i <= Areanum; ++i)
if (!deep[i]) dfs(i); for (int j = 1; j <= 17; ++j)
for (int i = 1; i <= Areanum; ++i) {
f[i][j] = f[f[i][j - 1]][j - 1];
c[i][j] = max(c[i][j - 1], c[f[i][j - 1]][j - 1]);
}
} int Query(int u, int v) {
if (find(u) != find(v)) return -1;
if (deep[u] < deep[v]) swap(u, v);
int d = deep[u] - deep[v], ans = 0;
for (int i = 17; i >= 0; --i)
if ((1 << i) & d) {
ans = max(ans, c[u][i]);
u = f[u][i];
}
if (u == v) return ans;
for (int i = 17; i >= 0; --i)
if (f[u][i] != f[v][i]) {
ans = max(ans, max(c[u][i], c[v][i]));
u = f[u][i];
v = f[v][i];
}
return max(ans, max(c[u][0], c[v][0]));
}
} int id[N * 3], nowx, rfl[N * 3]; bool cmpx(int x, int y) {
return P[x].x == P[y].x ? x < y : P[x].x < P[y].x;
} struct setnode {
Point u, v; int kind;
setnode(Point _u = Point(0, 0), Point _v = Point(0, 0), int _kind = 0)
: u(_u), v(_v), kind(_kind) {}
}; set <setnode> S;
set <setnode> :: iterator tmp; bool operator < (setnode A, setnode B) {
double kA = double(A.u.y) + double(nowx - A.u.x) / double(A.v.x) * A.v.y;
double kB = double(B.u.y) + double(nowx - B.u.x) / double(B.v.x) * B.v.y;
if (kA != kB) return kA < kB;
else return double(A.v.y) / double(A.v.x) < double(B.v.y) / double(B.v.x);
} int main() {
n = in(); M = in();
int x, y, z;
for (int i = 1; i <= n; ++i) {
x = in() << 1; y = in() << 1;
P[++tot] = Point(x, y);
} for (int i = 1; i <= M; ++i) {
x = in(); y = in(); z = in();
INIT::ins(x, y, z);
INIT::ins(y, x, z);
} INIT::init(); z = INIT::cnt;
for (int i = 2; i <= z; i += 2)
if (INIT::mark[i] != -1 && INIT::mark[i ^ 1] != -1)
MST::add(INIT::mark[i], INIT::mark[i ^ 1], INIT::E[i].h); MST::init(); int q = in(); double lx, ly;
for (int i = 1; i <= q; ++i) {
scanf("%lf%lf", &lx, &ly);
P[++tot] = Point(lx * 2, ly * 2);
scanf("%lf%lf", &lx, &ly);
P[++tot] = Point(lx * 2, ly * 2);
} for (int i = 1; i <= tot; ++i)
id[i] = i; int nowy, v;
stable_sort(id + 1, id + tot + 1, cmpx);// for (int i = 1; i <= tot; ++i) printf("%d ", id[i]); puts("");
for (int i = 1; i <= tot; ++i) {
x = id[i]; nowx = P[x].x; nowy = P[x].y;
if (x <= n) {
for (int j = INIT::point[x]; j; j = INIT::E[j].nxt) {
v = INIT::E[j].to;
if (P[v].x == P[x].x) continue;
if (P[v].x < P[x].x)
S.erase(setnode(P[v], P[x] - P[v], INIT::mark[j ^ 1]));
}
for (int j = INIT::point[x]; j; j = INIT::E[j].nxt) {
v = INIT::E[j].to;
if (P[v].x == P[x].x) continue;
if (P[v].x > P[x].x)
S.insert(setnode(P[x], P[v] - P[x], INIT::mark[j]));
}
} else {
tmp = S.upper_bound(setnode(P[x], Point(1, 0), 0));
// printf("upper_bound (%d,%d)->(%d,%d)\n", nowx, nowy, nowx + 1, nowy); if (tmp == S.end()) {
rfl[x] = -1;
// printf("rfl[%d] = %d (%d,%d)->(%d,%d)\n", x, rfl[x], tmp->u.x, tmp->u.y, tmp->u.x + tmp->v.x, tmp->u.y + tmp->v.y);
} else {
rfl[x] = tmp->kind;
// printf("rfl[%d] = %d (%d,%d)->(%d,%d)\n", x, rfl[x], tmp->u.x, tmp->u.y, tmp->u.x + tmp->v.x, tmp->u.y + tmp->v.y);
}
}
} for (int i = n + 1; i <= tot; i += 2) {
if (rfl[i] == -1 || rfl[i + 1] == -1)
puts("-1");
else
printf("%d\n", MST::Query(rfl[i], rfl[i + 1]));
} return 0;
}

没有删掉丑陋而愚蠢的调试信息(调个样例都调了半天写了一大堆调试信息这样以后注定要滚粗啊!)

【BZOJ 3051】【UOJ #57】【WC 2013】平面图的更多相关文章

  1. 【BZOJ 3052】【WC 2013】糖果公园

    对树的dfs序分块,打开了新世界的大门233 第一关键字是l所在的块,第二关键字是r所在的块,第三关键字是时间,分完块后暴力莫队即可 #include<cmath> #include< ...

  2. [LOJ 2720][BZOJ 5417][UOJ 395][NOI 2018]你的名字

    [LOJ 2720][BZOJ 5417][UOJ 395][NOI 2018]你的名字 题意 给定一个大串 \(S\) 以及 \(q\) 次询问, 每次询问给定一个串 \(T\) 和区间 \([l, ...

  3. [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)

    [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...

  4. BZOJ 4945 UOJ #317 NOI2017 游戏 2-SAT 拓扑排序

    http://uoj.ac/problem/317 https://www.lydsy.com/JudgeOnline/problem.php?id=4945 我现在的程序uoj的额外数据通过不了,b ...

  5. 洛谷 P2827 BZOJ 4721 UOJ #264 蚯蚓

    题目描述 本题中,我们将用符号表示对c向下取整,例如:. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现在共有n只蚯蚓(n为正整数).每只 ...

  6. BZOJ 3218 UOJ #77 A+B Problem (主席树、最小割)

    大名鼎鼎的A+B Problem, 主席树优化最小割-- 调题死活调不对,一怒之下改了一种写法交上去A了,但是改写法之后第4,5个点常数变大很多,于是喜提UOJ全站倒数第三 目前还不知道原来的写法为什 ...

  7. BZOJ 4734 UOJ #269 如何优雅地求和 (多项式)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4734 (UOJ) http://uoj.ac/problem/269 题解 ...

  8. BZOJ 4732 UOJ #268 [清华集训2016]数据交互 (树链剖分、线段树)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4732 (UOJ) http://uoj.ac/problem/268 题解 ...

  9. bzoj 1001: [BeiJing2006]狼抓兔子 平面图最小割

    平面图跑最大流 可以转换为其对偶图跑最短路 一个环对应一个割  找到最小环(即最短路)极为所求,注意辅助边的建立 加入读入优化  不过时间还是一般  估计是dij写的不好   大神勿喷~~~ /*** ...

随机推荐

  1. 自己实现苹果安装app动画

    最近在学习CALayer相关动画,然后某一天突然发现苹果安装app这动画就很不错啊,所以就想自己实现下. 具体效果如图: 还是不试不知道一试吓一跳啊,这看上去简单的动画没我想象的那么简单. 首先这个动 ...

  2. React Native常用组件Image使用

    前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会有所 ...

  3. NSCopy&NSMutableCopy

    struct student { int a; float f; char c; long l; }; struct person { int a; float f; char c; long l; ...

  4. Core Data的一些常见用法

    一.简介 Core Data是一个纯粹的面向对象框架,其本质就是一个ORM(对象关系映射:Object Relational Mapping),能以面向对象的方式操作SQLite数据库.在实际开发中绝 ...

  5. React Native 红屏之Could not connect to development server.

    React Native 是目前最火的开发框架,其他不说了,上Bug. 按照  React Native iOS环境搭建 高级版 在mac上  搭建 React Native  环境,运行 项目 若出 ...

  6. ASP.NET MVC中Unobtrusive Ajax的妙用

    Unobtrusive Javascript有三层含义:一是在HTML代码中不会随意的插入Javsscript代码,只在标签中加一些额外的属性值,然后被引用的脚本文件识别和处理:二是通过脚本文件所增加 ...

  7. x01.Weiqi.11: 神来之笔

    在围棋中,一子两用,可谓妙手,而一子三用,则可称之为神来之笔.在解决征子问题时,一不小心,也来了个神来之笔,其代码如下: // 征子判断,p1, p2 为气,p2 为前进方向,p 为逃跑之子. boo ...

  8. android 发送短信功能

    private void sendSMS(String num,String smsBody) { String phoneNum = "smsto:" + num; Uri sm ...

  9. linux中通配符和常用特殊符号

    1 通配符   2 特殊符号 3 参考文档 鸟哥的私房菜 http://vbird.dic.ksu.edu.tw/linux_basic/0320bash_4.php#settings_wildcar ...

  10. git cherry-pick合并某个commit

    1.使用方法及其作用 git cherry-pick可以选择某一个分支中的一个或几个commit(s)来进行操作(操作的对象是commit).例如,假设我们有个稳定版本的分支,叫v2.0,另外还有个开 ...