Circle的构造函数没赋初值都能过样例真是厉害啊……
这题做法比较显然。巫师和精灵构成了二分图,第i个巫师能干的精灵个数就是⌊Titime+1⌋,判断所有精灵能否被干完的话跑个最大流就完事了。
至于时间,显然具有单调性,于是二分之。
没了。
判断线段和圆相交的话另外写一篇文章好了。
设网络流时间复杂度为O(F),则总时间复杂度为O((F+nm)logtime)。
网络流直接上了vani的模板。
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a,_=b;i<=_;i++)
#define per(i,a,b) for(int i=a,_=b;i>=_;i--)
#define For(i,a,b) for(int i=a,_=b;i< _;i++)
#define maxn 203
inline int rd() {
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar() ; int x = 0 , f = 1;
if (c == '-') f = -1 ; else x = c - '0';
while (isdigit(c = getchar())) x = x * 10 + c - '0';
return x * f;
}
//===========================NetworkFlow===============
const int NFmaxn = 3005;
const int NFmaxm = 600005;
const int NFinf = 0x7fffffff;
struct NF_Line
{
int to, next, v, opt;
};
struct Network_Flow
{
NF_Line li[NFmaxm];
int be[NFmaxn], l, s, t, n, num[NFmaxn], note[NFmaxn];
void makeline(int fr, int to, int v)
{
++l;
li[l].next = be[fr];
be[fr] = l;
li[l].to = to;
li[l].v = v;
li[l].opt = l + 1;
++l;
li[l].next = be[to];
be[to] = l;
li[l].to = fr;
li[l].v = 0;
li[l].opt = l - 1;
}
void create(int N)
{
n = N;
}
int sap(int now, int maxf)
{
if (now == t) return maxf;
int mi = n, tot = 0;
for (int i = be[now]; i; i = li[i].next)
{
int to = li[i].to;
if (li[i].v && note[to] + 1 == note[now])
{
int k = sap(to, min(maxf - tot, li[i].v));
li[i].v -= k;
tot += k;
li[li[i].opt].v += k;
if (note[s] >= n || tot == maxf) return tot;
}
if (li[i].v) mi = min(mi, note[to]);
}
if (!tot)
{
if (!--num[note[now]])
{
note[s] = n;
return 0;
}
++num[note[now] = mi + 1];
}
return tot;
}
int query(int S, int T)
{
s = S, t = T;
memset(num, 0, sizeof(num));
memset(note, 0, sizeof(note));
num[0] = n;
int ans = 0;
while (note[s] < n) ans += sap(s, NFinf);
return ans;
}
void clear()
{
l = s = t = n = 0;
memset(be, 0, sizeof(be));
memset(num, 0, sizeof(num));
memset(note, 0, sizeof(note));
}
}SAP;
//===========================NetworkFlow===============
vector<int> rel[maxn];
const int inf = 0x7fffffff;
inline void upmin(int&a , int b) { if (a > b) a = b ; }
inline void upmax(int&a , int b) { if (a < b) a = b ; }
template<class T> inline T sqr(T x) { return x * x ; }
struct Point {
int x , y;
Point(int x = 0 , int y = 0):x(x) , y(y) { }
friend Point operator-(Point a , Point b) { return Point(a.x - b.x , a.y - b.y) ; }
inline void print() { printf("%d %d\n" , x , y) ; }
}b[maxn];
struct Circle {
Point o;
int r;
Circle() { o = Point() , r = 0 ; }
Circle(Point o , int r):o(o) , r(r) { }
inline void print() { printf("%d " , r) , o.print() ; }
}a[maxn] , c[maxn];
struct Line {
Point a , b;
Line() { a = b = Point();}
Line(Point a , Point b):a(a) , b(b) {}
};
int n , m , K , mx , t[maxn];
void input() {
n = rd() , m = rd() , K = rd();
rep (i , 1 , n) {
int x = rd() , y = rd() , r = rd();
t[i] = rd();
upmax(mx , t[i]);
a[i] = Circle(Point(x , y) , r);
}
rep (i , 1 , m) {
int x = rd() , y = rd();
b[i] = Point(x , y);
}
rep (i , 1 , K) {
int x = rd() , y = rd() , r = rd();
c[i] = Circle(Point(x , y) , r);
}
}
inline double cross(Point a , Point b) {
return a.x * b.y - a.y * b.x;
}
inline double dot(Point a , Point b) {
return a.x * b.x + a.y * b.y;
}
inline double DotToDotDis(Point a , Point b) {
return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
}
inline double DotToSegDis(Point p , Line l) {
if (dot(l.a - p , l.b - p) > 0) return min(DotToDotDis(l.a , p) , DotToDotDis(l.b , p));
return fabs(cross(p - l.a , l.b - l.a)) / DotToDotDis(l.a , l.b);
}
inline bool ok(Circle a , Point b) {
if (DotToDotDis(a.o , b) > a.r) return 0;
rep (k , 1 , K)
if (DotToSegDis(c[k].o , Line(a.o , b)) < c[k].r) return 0;
return 1;
}
void GetIntersect() {
rep (i , 1 , n) rep (j , 1 , m) if (ok(a[i] , b[j]))
rel[i].push_back(j);
}
int check(int mid) {
SAP.clear();
SAP.create(n + m + 2);
rep (i , 1 , n) {
SAP.makeline(n + m + 1 , i , mid / t[i] + 1);
For (j , 0 , rel[i].size()) {
int x = rel[i][j];
SAP.makeline(i , x + n , 1);
}
}
rep (i , 1 , m) SAP.makeline(i + n , n + m + 2 , 1);
return SAP.query(n + m + 1 , n + m + 2);
}
void solve() {
GetIntersect();
int l = 0 , r = m * mx , ans = inf;
while (l <= r) {
int mid = (l + r) >> 1;
int cnt = check(mid);
if (cnt == m) upmin(ans , mid) , r = mid - 1;
else l = mid + 1;
}
printf("%d\n" , ans == inf ? -1 : ans);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt" , "r" , stdin);
#endif
input();
solve();
return 0;
}