BZOJ1822 [JSOI2010]Frozen Nova 冷冻波 二分+最大流
题目传送门
https://lydsy.com/JudgeOnline/problem.php?id=1822
题解
好久没做网络流的,都没有想到网络流...
首先暴力判断一下一个巫妖和一个精灵之间能否攻击到。大体上就是枚举树,求一下圆心到巫妖和精灵的连线段的距离,和半径比较一下就可以了。
然后巫妖向能攻击到的精灵建边。然后二分答案 \(mid\),从 $S $ 向每个精灵建一条容量为 \(\lfloor\frac {mid}t\rfloor + 1\) 的边,每个精灵向 \(T\) 建一个 \(1\) 的边。跑最大流就可以了。
下面是代码。因为这是一个二分图,所以一次 Dinic 的复杂度为 \(O(m\sqrt n) = O(n^{\frac 52})\)。因此总的时间复杂度为 \(O(\operatorname{Dinic}(n, n^2)\log ans)\)。
#include<bits/stdc++.h>
#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back
template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}
typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
template<typename I>
inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
}
const int NN = 200 + 7;
const int N = 200 * 2 + 2 + 7;
const int M = 200 * 200 + 200 * 2 + 7;
const int INF = 0x3f3f3f3f;
const double eps = 1e-10;
int n, m, k, nod, allsize, S, T, tot1, mxt, hd, tl;
int ar[NN], at[NN], cr[NN];
int dis[N], cur[N], q[N];
struct Point {
int x, y;
inline Point() {}
inline Point(const int &x, const int &y) : x(x), y(y) {}
} a[NN], b[NN], c[NN];
inline Point operator - (const Point &a, const Point &b) { return Point(a.x - b.x, a.y - b.y);}
inline int dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }
inline int cross(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x;}
//inline double dist(const Point &a, const Point &b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); }
inline int dist2(const Point &a, const Point &b) { return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y); }
struct Edge { int to, ne, f; } g[M << 1]; int head[N], tot = 1;
inline void addedge(int x, int y, int z) { g[++tot].to = y, g[tot].f = z, g[tot].ne = head[x], head[x] = tot;}
inline void adde(int x, int y, int z) { addedge(x, y, z), addedge(y, x, 0); }
inline bool bfs() {
memset(dis, 0x3f, allsize), memcpy(cur, head, allsize);
q[hd = 0, tl = 1] = S, dis[S] = 0;
while (hd < tl) {
int x = q[++hd];
for fec(i, x, y) if (g[i].f && dis[y] == INF) {
dis[y] = dis[x] + 1, q[++tl] = y;
if (y == T) return 1;
}
}
return 0;
}
inline int dfs(int x, int a) {
if (x == T || !a) return a;
int flow = 0, f;
for (int &i = cur[x]; i; i = g[i].ne) {
int y = g[i].to;
if (dis[y] != dis[x] + 1 || !(f = dfs(y, std::min(a, g[i].f)))) continue;
g[i].f -= f, g[i ^ 1].f += f;
flow += f, a -= f;
if (!a) break;
}
if (!flow) dis[x] = INF;
return flow;
}
inline int dinic() {
int ans = 0;
while (bfs()) ans += dfs(S, INF);
return ans;
}
inline void build() {
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j) if (dist2(a[i], b[j]) <= ar[i] * ar[i]) {
bool flag = 1;
for (int kk = 1; kk <= k; ++kk) {
int s = abs(cross(b[j] - a[i], c[kk] - a[i]));
if ((ll)dot(c[kk] - b[j], a[i] - b[j]) * dot(c[kk] - a[i], b[j] - a[i]) > 0 && (ll)s * s <= (ll)cr[kk] * cr[kk] * dist2(b[j], a[i])) { flag = 0; break; }
if (dist2(c[kk], b[j]) <= cr[kk] * cr[kk] || dist2(c[kk], a[i]) <= cr[kk] * cr[kk]) { flag = 0; break; }
}
if (flag) adde(i, j + n, 1);
}
S = n + m + 1, nod = T = S + 1, allsize = (nod + 1) * sizeof(int);
for (int i = 1; i <= m; ++i) adde(i + n, T, 1);
tot1 = tot;
for (int i = 1; i <= n; ++i) adde(S, i, 0);
}
inline bool check(const int &mid) {
for (int i = 2; i <= tot1; i += 2) g[i].f = 1, g[i ^ 1].f = 0;
for (int i = 1, j = tot1 + 1; i <= n; ++i, j += 2) g[j].f = mid / at[i] + 1, g[j ^ 1].f = 0;
return dinic() >= m;
}
inline void work() {
build();
int l = 0, r = mxt * m;
while (l < r) {
int mid = (l + r) >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
if (!check(l)) puts("-1");
else printf("%d\n", l);
}
inline void init() {
read(n), read(m), read(k);
for (int i = 1; i <= n; ++i) read(a[i].x), read(a[i].y), read(ar[i]), read(at[i]), smax(mxt, at[i]);
for (int i = 1; i <= m; ++i) read(b[i].x), read(b[i].y);
for (int i = 1; i <= k; ++i) read(c[i].x), read(c[i].y), read(cr[i]);
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
BZOJ1822 [JSOI2010]Frozen Nova 冷冻波 二分+最大流的更多相关文章
- 1822: [JSOI2010]Frozen Nova 冷冻波 二分最大流
1822: [JSOI2010]Frozen Nova 冷冻波 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 585 Solved: 175[Subm ...
- Bzoj1822 [JSOI2010]Frozen Nova 冷冻波
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1933 Solved: 608 Description WJJ喜欢“魔兽争霸”这个游戏.在游戏中,巫妖 ...
- 【计算几何】【二分答案】【最大流】bzoj1822 [JSOI2010]Frozen Nova 冷冻波
用三角形面积什么的算算点到直线的距离之类……其实相切的情况是可行的……剩下的就跟某SDOI2015一样了. #include<cstdio> #include<cmath> # ...
- bzoj1822: [JSOI2010]Frozen Nova 冷冻波网络流
思路比较显然:二分答案,流流流 但是实现的时候感觉自己数学捉急.. 一开始算了个直线到点距离.... 应该是线段到点距离 #include <bits/stdc++.h> #define ...
- 【BZOJ1822】[JSOI2010]Frozen Nova 冷冻波 几何+二分+网络流
[BZOJ1822][JSOI2010]Frozen Nova 冷冻波 Description WJJ喜欢“魔兽争霸”这个游戏.在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀 ...
- 【bzoj1822】[JSOI2010]Frozen Nova 冷冻波 计算几何+二分+网络流最大流
题目描述 WJJ喜欢“魔兽争霸”这个游戏.在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵.我们认为,巫妖和小精灵都可以看成是平面上的点. 当巫妖和小精灵之间的直线 ...
- BZOJ 1822 Frozen Nova 冷冻波(最大流)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1822 题意:WJJ喜欢“魔兽争霸”这个游戏.在 游戏中,巫妖是一种强大的英雄,它的技能F ...
- BZOJ 1822[JSOI2010]Frozen Nova 冷冻波
网络流+二分. n^3枚举判断每个巫妖可以攻击的精灵,向其连1的边,每个精灵向汇点连1的边. 二分答案,修改源点流向每个巫妖的cap,跑最大流看是否等于精灵数. 恩,看起来没什么毛病. 然后狂WA不止 ...
- BZOJ-1822 Frozen Nova 冷冻波 计(jie)算(xi)几何+二分+最大流判定+经典建图
这道逼题!感受到了数学对我的深深恶意(#‵′).... 1822: [JSOI2010]Frozen Nova 冷冻波 Time Limit: 10 Sec Memory Limit: 64 MB S ...
随机推荐
- 5G即将到来!我们需要一部怎样的手机呢?
随着5G技术研发试验即将于年底宣告完成,也就意味着2019年起,5G商用将会宣布启动,现在OPPO.vivo.小米.华为.一加等众多手机厂商也宣布启动5G计划,这时5G势必会掀起一股新鲜的血液,5G手 ...
- 解决kubernetes拉取不了镜像仓库的问题
将镜像仓库地址k8s.gcr.io改成registry.aliyuncs.com/google_containers
- HihoCoder - 1104 Suzhou Adventure (树上背包)
题目:https://vjudge.net/contest/323605#problem/D 题意:给你一棵n个点的树,1点出发,然后规定k个点必须去,每个点上有一个权值,要走m个点,问最大权值是多少 ...
- C/C++ | 并查集:用于检查一个图上有没有环
没有环的过程分析: #include<stdio.h> #include<stdlib.h> #include<iostream> #define VERTICE ...
- linux 统计代码行数
列出目录下所有文件(仅有文件名):ls -laR 列出目录下所有文件名称find . * 统计当前目录下全部代码行数find . * | xargs wc -l 统计当前目录下java文件行数,去除空 ...
- 双轴按键摇杆控制器控制TFTLCD(使用ADC1双通道DMA传输)
实验使用如下所示的双轴按键摇杆控制器,来控制TFTLCD上显示的直线.首先介绍一下双轴按键摇杆控制器.原理:十字摇杆为一个双向的10K电阻器,随着摇杆方向不同,抽头的阻值随着变化.本模块使用5V供电( ...
- 一个使用Spring的AspectJ LTW的简单例子
参考:Spring Framework Reference Documentation Spring AOP 实现原理与 CGLIB 应用 比较分析 Spring AOP 和 AspectJ 之间的差 ...
- Vagrant 手册之同步目录 - VirtualBox
原文地址 如果你使用的 provider 是 VirtualBox,那么 VirtualBox 同步目录就是默认的同步目录类型.这些同步目录使用 VirtualBox 的共享目录系统来同步客户机跟宿主 ...
- 【转载】Spring boot学习记录(三)-启动原理解析
前言:本系列文章非本人原创,转自:http://tengj.top/2017/04/24/springboot0/ 正文 我们开发任何一个Spring Boot项目,都会用到如下的启动类 @Sprin ...
- SEC3 - MySQL常见命令
1.查看当前所有的数据库 show databases; 2. 打开指定的库名 use 库名称: 3.查看当前库中所有的表 show tables; 4. 查看其他库的所有表 show tables ...