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行,好长啊。。

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

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

  1. #include<set>
  2. #include<cmath>
  3. #include<vector>
  4. #include<cstdio>
  5. #include<cstring>
  6. #include<algorithm>
  7. using namespace std;
  8. const int N = 100003;
  9. typedef long long ll;
  10. int in() {
  11. int k = 0, fh = 1; char c = getchar();
  12. for(; c < '0' || c > '9'; c = getchar())
  13. if (c == '-') fh = -1;
  14. for(; c >= '0' && c <= '9'; c = getchar())
  15. k = k * 10 + c - 48;
  16. return k * fh;
  17. }
  18. int n, M, Areanum;
  19. struct Point {
  20. int x, y;
  21. Point(int _x = 0, int _y = 0)
  22. : x(_x), y(_y) {}
  23. Point operator + (const Point &A) const {
  24. return Point(x + A.x, y + A.y);
  25. }
  26. Point operator - (const Point &A) const {
  27. return Point(x - A.x, y - A.y);
  28. }
  29. } P[N * 3];
  30. int tot = 0;
  31. namespace INIT {
  32. struct node {int nxt, to, h, from;} E[N << 1];
  33. int cnt = 1, nt[N << 1], mark[N << 1], st[N << 1], point[N];
  34. struct data {
  35. int id; double num;
  36. data(int _id = 0, double _num = 0) : id(_id), num(_num) {}
  37. bool operator < (const data &A) const {
  38. return num < A.num;
  39. }
  40. } D[N];
  41. void ins(int u, int v, int w) {E[++cnt] = (node) {point[u], v, w, u}; point[u] = cnt;}
  42. ll Cross(int a, int b) {
  43. return (ll) P[a].x * P[b].y - (ll) P[a].y * P[b].x;
  44. }
  45. void init() {
  46. int m, top, tmp, from;
  47. ll Cro;
  48. for (int i = 1; i <= n; ++i) {
  49. m = 0;
  50. for (int j = point[i]; j; j = E[j].nxt)
  51. D[++m] = data(j, atan2(double(P[E[j].to].y - P[i].y), double(P[E[j].to].x - P[i].x)));
  52. stable_sort(D + 1, D + m + 1);
  53. for (int j = 1; j < m; ++j)
  54. nt[D[j].id] = D[j + 1].id;
  55. nt[D[m].id] = D[1].id;
  56. // printf("---PointID = %d---m = %d---\n", i, m);
  57. // for(int j = 1; j <= m; ++j) printf("%d ", E[D[j].id].to);
  58. // puts("");
  59. }
  60. m = 0;
  61. for (int i = 2; i <= cnt; ++i)
  62. if (!mark[i]) {
  63. from = E[i].from;
  64. top = 1;
  65. st[1] = i;
  66. Cro = Cross(from, E[i].to);
  67. tmp = nt[i ^ 1];
  68. while (E[tmp].to != from) {
  69. st[++top] = tmp;
  70. Cro += Cross(E[tmp].from, E[tmp].to);
  71. tmp = nt[tmp ^ 1];
  72. }
  73. Cro += Cross(E[tmp].from, from);
  74. if (Cro > 0) {
  75. mark[tmp] = -1;
  76. while (top) mark[st[top--]] = -1;
  77. } else {
  78. mark[tmp] = ++m;
  79. while (top) mark[st[top--]] = m;
  80. }
  81. }
  82. // for (int i = 2; i <= cnt; ++i)
  83. // printf("%d ---> %d RightSide : %d\n", E[i].from, E[i].to, mark[i]);
  84. Areanum = m;
  85. }
  86. }
  87. namespace MST {
  88. struct Ed {
  89. int u, v, w;
  90. bool operator < (const Ed &A) const {
  91. return w < A.w;
  92. }
  93. } EDGE[N << 1];
  94. struct node {int nxt, to, w;} E[N << 1];
  95. int tot2 = 0, cnt = 0, deep[N], f[N][18], c[N][18], point[N], fa[N];
  96. void add(int u, int v, int w) {
  97. EDGE[++tot2] = (Ed) {u, v, w};
  98. // printf("%d <===dis = %d===> %d\n", u, w, v);
  99. }
  100. void ins(int u, int v, int w) {E[++cnt] = (node) {point[u], v, w}; point[u] = cnt;}
  101. int find(int x) {return fa[x] == x ? x : fa[x] = find(fa[x]);}
  102. void dfs(int x) {
  103. for (int i = point[x]; i; i = E[i].nxt)
  104. if (E[i].to != f[x][0]) {
  105. f[E[i].to][0] = x;// printf("%d --fadis = %d--> %d\n", E[i].to, E[i].w, x);
  106. c[E[i].to][0] = E[i].w;
  107. deep[E[i].to] = deep[x] + 1;
  108. dfs(E[i].to);
  109. }
  110. }
  111. void init() {
  112. stable_sort(EDGE + 1, EDGE + tot2 + 1);
  113. for (int i = 1; i <= Areanum; ++i)
  114. fa[i] = i;
  115. int x, y, fx, fy, con = 0;
  116. for (int i = 1; i <= tot2; ++i) {
  117. x = EDGE[i].u; y = EDGE[i].v;
  118. fx = find(x); fy = find(y);
  119. if (fx != fy) {
  120. ++con;
  121. if (con == Areanum) break;
  122. fa[fx] = fy;
  123. ins(x, y, EDGE[i].w);
  124. ins(y, x, EDGE[i].w);
  125. }
  126. }
  127. for (int i = 1; i <= Areanum; ++i)
  128. if (!deep[i]) dfs(i);
  129. for (int j = 1; j <= 17; ++j)
  130. for (int i = 1; i <= Areanum; ++i) {
  131. f[i][j] = f[f[i][j - 1]][j - 1];
  132. c[i][j] = max(c[i][j - 1], c[f[i][j - 1]][j - 1]);
  133. }
  134. }
  135. int Query(int u, int v) {
  136. if (find(u) != find(v)) return -1;
  137. if (deep[u] < deep[v]) swap(u, v);
  138. int d = deep[u] - deep[v], ans = 0;
  139. for (int i = 17; i >= 0; --i)
  140. if ((1 << i) & d) {
  141. ans = max(ans, c[u][i]);
  142. u = f[u][i];
  143. }
  144. if (u == v) return ans;
  145. for (int i = 17; i >= 0; --i)
  146. if (f[u][i] != f[v][i]) {
  147. ans = max(ans, max(c[u][i], c[v][i]));
  148. u = f[u][i];
  149. v = f[v][i];
  150. }
  151. return max(ans, max(c[u][0], c[v][0]));
  152. }
  153. }
  154. int id[N * 3], nowx, rfl[N * 3];
  155. bool cmpx(int x, int y) {
  156. return P[x].x == P[y].x ? x < y : P[x].x < P[y].x;
  157. }
  158. struct setnode {
  159. Point u, v; int kind;
  160. setnode(Point _u = Point(0, 0), Point _v = Point(0, 0), int _kind = 0)
  161. : u(_u), v(_v), kind(_kind) {}
  162. };
  163. set <setnode> S;
  164. set <setnode> :: iterator tmp;
  165. bool operator < (setnode A, setnode B) {
  166. double kA = double(A.u.y) + double(nowx - A.u.x) / double(A.v.x) * A.v.y;
  167. double kB = double(B.u.y) + double(nowx - B.u.x) / double(B.v.x) * B.v.y;
  168. if (kA != kB) return kA < kB;
  169. else return double(A.v.y) / double(A.v.x) < double(B.v.y) / double(B.v.x);
  170. }
  171. int main() {
  172. n = in(); M = in();
  173. int x, y, z;
  174. for (int i = 1; i <= n; ++i) {
  175. x = in() << 1; y = in() << 1;
  176. P[++tot] = Point(x, y);
  177. }
  178. for (int i = 1; i <= M; ++i) {
  179. x = in(); y = in(); z = in();
  180. INIT::ins(x, y, z);
  181. INIT::ins(y, x, z);
  182. }
  183. INIT::init();
  184. z = INIT::cnt;
  185. for (int i = 2; i <= z; i += 2)
  186. if (INIT::mark[i] != -1 && INIT::mark[i ^ 1] != -1)
  187. MST::add(INIT::mark[i], INIT::mark[i ^ 1], INIT::E[i].h);
  188. MST::init();
  189. int q = in(); double lx, ly;
  190. for (int i = 1; i <= q; ++i) {
  191. scanf("%lf%lf", &lx, &ly);
  192. P[++tot] = Point(lx * 2, ly * 2);
  193. scanf("%lf%lf", &lx, &ly);
  194. P[++tot] = Point(lx * 2, ly * 2);
  195. }
  196. for (int i = 1; i <= tot; ++i)
  197. id[i] = i;
  198. int nowy, v;
  199. stable_sort(id + 1, id + tot + 1, cmpx);// for (int i = 1; i <= tot; ++i) printf("%d ", id[i]); puts("");
  200. for (int i = 1; i <= tot; ++i) {
  201. x = id[i]; nowx = P[x].x; nowy = P[x].y;
  202. if (x <= n) {
  203. for (int j = INIT::point[x]; j; j = INIT::E[j].nxt) {
  204. v = INIT::E[j].to;
  205. if (P[v].x == P[x].x) continue;
  206. if (P[v].x < P[x].x)
  207. S.erase(setnode(P[v], P[x] - P[v], INIT::mark[j ^ 1]));
  208. }
  209. for (int j = INIT::point[x]; j; j = INIT::E[j].nxt) {
  210. v = INIT::E[j].to;
  211. if (P[v].x == P[x].x) continue;
  212. if (P[v].x > P[x].x)
  213. S.insert(setnode(P[x], P[v] - P[x], INIT::mark[j]));
  214. }
  215. } else {
  216. tmp = S.upper_bound(setnode(P[x], Point(1, 0), 0));
  217. // printf("upper_bound (%d,%d)->(%d,%d)\n", nowx, nowy, nowx + 1, nowy);
  218. if (tmp == S.end()) {
  219. rfl[x] = -1;
  220. // 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);
  221. } else {
  222. rfl[x] = tmp->kind;
  223. // 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);
  224. }
  225. }
  226. }
  227. for (int i = n + 1; i <= tot; i += 2) {
  228. if (rfl[i] == -1 || rfl[i + 1] == -1)
  229. puts("-1");
  230. else
  231. printf("%d\n", MST::Query(rfl[i], rfl[i + 1]));
  232. }
  233. return 0;
  234. }

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

【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. 在其他系统Iframe中显示SharePoint 页面

    前段时间在做一个项目,要求将SharePoint 的 OWA(Office Web Apps)中的文档显示页面嵌入到另外一个OA系统中,提供给用户可以通过浏览器查看SharePoint文档的能力. 嵌 ...

  2. QuickFlow UI 控件之 NamedFormAttachment

    在开发自定义表单时,如果碰到需要按类别上传附件的情况,(比如流程附件分为草稿版,正式版,发布版),比较难处理,需要开发自定义字段控件来实现. QF最新版本(Build131124)提供了NamedFo ...

  3. 一起来学习Android自定义控件2-简单的写字板控件

    概述 上一篇文章我们对自定义控件进行了一个大体的知识介绍.今天就来学习自定义一个简单的写字板控件. 先来看看效果图 就是简单的根据手指写下的轨迹去画出内容 实现 在上一篇文章里提到了android官方 ...

  4. 如何转换SQL Server 2008数据库到SQL Server 2005

        背景介绍: 公司一套系统使用的是SQL SERVER 2008数据库,突然一天收到邮件,需要将这套系统部署到各个不同地方(海外)的工厂,需要在各个工厂部署该数据库,等我将准备工作做好,整理文档 ...

  5. oracle行转列与列转行

    一.行转列 在有些应用场景中,如学生成绩.学生所有科目的成绩都保存到一张表里面,当我们需要以列表的形式显示出学生所对应的每一科目的成绩的时候,需要使用到行转列. 示例 -- 学生成绩表 create ...

  6. Linux IPC udp/tcp/UNIX域 socket编程

    UNIX域套接字本地通信即在socket第一个参数中选择AF_LOCAL,socket是BSD提出的一种适用于所有的情况的进程间通信的方式,虽然现在多用于网络通信,但是本机内的进程间通信也是没有问题的 ...

  7. WPF 自定义柱状图 BarChart

    WPF 自定义柱状图 当前的Telerik控件.DevExpress控件在图表控件方面做得不错,但是有时项目中需要特定的样式,不是只通过修改图表的模板和样式就能实现的. 或者说,通过修改当前的第三方控 ...

  8. Android之android:launchMode

    (本文转自:http://www.eoeandroid.com/blog-531377-3446.html) (详细查看:http://blog.csdn.net/liuhe688/article/d ...

  9. js跨域那些事

    原文:http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html 什么是跨域 JavaScript出于安全方面的考虑,不允许跨域调用其 ...

  10. linux命令之tail

    tail用于输出文件末尾部分.一个比较有用的功能是tail + grep实现类似于安卓开发时调试使用的logcat,具体操作是: 一般我是用SecureCRT连接linux,然后使用SecureCRT ...