【BZOJ 3051】【UOJ #57】【WC 2013】平面图
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】平面图的更多相关文章
- 【BZOJ 3052】【WC 2013】糖果公园
对树的dfs序分块,打开了新世界的大门233 第一关键字是l所在的块,第二关键字是r所在的块,第三关键字是时间,分完块后暴力莫队即可 #include<cmath> #include< ...
- [LOJ 2720][BZOJ 5417][UOJ 395][NOI 2018]你的名字
[LOJ 2720][BZOJ 5417][UOJ 395][NOI 2018]你的名字 题意 给定一个大串 \(S\) 以及 \(q\) 次询问, 每次询问给定一个串 \(T\) 和区间 \([l, ...
- [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)
[BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...
- BZOJ 4945 UOJ #317 NOI2017 游戏 2-SAT 拓扑排序
http://uoj.ac/problem/317 https://www.lydsy.com/JudgeOnline/problem.php?id=4945 我现在的程序uoj的额外数据通过不了,b ...
- 洛谷 P2827 BZOJ 4721 UOJ #264 蚯蚓
题目描述 本题中,我们将用符号表示对c向下取整,例如:. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现在共有n只蚯蚓(n为正整数).每只 ...
- BZOJ 3218 UOJ #77 A+B Problem (主席树、最小割)
大名鼎鼎的A+B Problem, 主席树优化最小割-- 调题死活调不对,一怒之下改了一种写法交上去A了,但是改写法之后第4,5个点常数变大很多,于是喜提UOJ全站倒数第三 目前还不知道原来的写法为什 ...
- BZOJ 4734 UOJ #269 如何优雅地求和 (多项式)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4734 (UOJ) http://uoj.ac/problem/269 题解 ...
- BZOJ 4732 UOJ #268 [清华集训2016]数据交互 (树链剖分、线段树)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4732 (UOJ) http://uoj.ac/problem/268 题解 ...
- bzoj 1001: [BeiJing2006]狼抓兔子 平面图最小割
平面图跑最大流 可以转换为其对偶图跑最短路 一个环对应一个割 找到最小环(即最短路)极为所求,注意辅助边的建立 加入读入优化 不过时间还是一般 估计是dij写的不好 大神勿喷~~~ /*** ...
随机推荐
- Android Do not keep activities选项分析
Android Do not keep activities选项分析 Developer Options里面有一项: Do not keep activities -> 不保留Activitie ...
- [Objective-C]关联(objc_setAssociatedObject、objc_getAssociatedObject、objc_removeAssociatedObjects)
关联 关联是指把两个对象相互关联起来,使得其中的一个对象作为另外一个对象的一部分. 关联特性只有在Mac OS X V10.6以及以后的版本上才是可用的. 在类的定义之外为类增加额外的存储空间 ...
- IOS开发基础知识--碎片33
1:AFNetworking状态栏网络请求效果 直接在AppDelegate里面didFinishLaunchingWithOptions进行设置 [[AFNetworkActivityIndicat ...
- 数据仓库之SSIS开发
1.从cdc捕获到数据以后, 连接ssis进行执行数据的抽取以及转换工作,把需要的数据导入到数据仓库, 并且做好对应的日志记录表.现在先说一下比较重要的. 选择参数化设置数据连接, 以方便后面的配置. ...
- Nginx反向代理和负载均衡部署指南
1. 安装 1) 从Nginx官网下载页面(http://nginx.org/en/download.html)下载Nginx最新版本(目前是1.5.13版本)安装包: ...
- Java导入的项目乱码怎么解决?(Ⅰ)
1.项目右键 打开 >> Properties >> Resource >> Text file encoding >> Other 如 ...
- MS SQL 需要定期清理日志文件
前言碎语 关于对SQL SERVER 日志文件管理方面了解不多的话,可以参考我的这篇博客文章“MS SQL 日志记录管理”,不过这篇文章只是介绍对SQL SERVER日志记录的深入认知了解,并没有提出 ...
- C# Attribute学习
由于项目中需要使用到序列化相关的技术,从而想到是否可以使用C#中的特性,特此花了近两小时学习了一下. 对于特性的学习,主要参考了两篇博文,特此感谢.以下附链接: http://www.cnblogs. ...
- [AlwaysOn Availability Groups]排查:AG超过RTO
排查:AG超过RTO 自动故障转移或者手动转移之后,没有数据都是,你可能会发现切换时间超过了你的RTO.或者当你评估切换时间同步提交secondary副本,发现超过了你的RTO. 1. 通常原因 通常 ...
- asp.net signalR 专题—— 第三篇 如何从外部线程访问 PersistentConnection
在前面的两篇文章中,我们讲到的都是如何将消息从server推向client,又或者是client再推向server,貌似这样的逻辑没什么异常,但是放在真实 的环境中,你会很快发现有一个新需求,如何根据 ...