JSOI2010第二轮Contest1
其实我只想打个网络流,但莫名其妙开始打计算几何
网络流部分比较简单,二分时间,这样每个巫妖的伤害数量上限已经确定了
S向巫妖连 t i m e t i + 1 \frac{time}{t_i}+1 titime+1边,巫妖向可以打到的精灵连1边,精灵向T连1边
判断最大流是否为精灵数就可以了
然后就是判断圆是否和线段有交
圆到线段的距离是 叉 积 线 段 长 度 \frac{叉积}{线段长度} 线段长度叉积,因为叉积可以看成围成的平行四边形的面积
如果圆到线段的点不在线段上,这样点积为负,这时只需判断是否会覆盖端点就可以了
#include
#include
#include
#include
#include
using namespace std;
#define dd c=getchar()
int read() {int s=0,w=1;char c;while (dd,c>'9' || c<'0') if (c=='-') w=-1;while (c>='0' && c<='9') s=s*10+c-'0',dd;return s*w;}
#undef dd
void write(int x) {if (x<0) putchar('-'),x=-x;if (x>=10) write(x/10);putchar(x%10|'0');}
void wln(int x) {write(x);putchar('\n');}void wsp(int x) {write(x);putchar(' ');}
const int N = 205;
struct node {
double x,y;
}a[N],b[N],c[N];
node operator -(node a, node b) {return (node) {a.x-b.x, a.y-b.y};}
double operator *(node a, node b) {return a.x*b.x+a.y*b.y;}
double operator ^(node a, node b) {return a.x*b.y-a.y*b.x;}
double sqr(int x) {return x*x;}
double dis(node a, node b) {return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
struct edge {
int t, nxt, w;
}e[N*N*5];
int n,m,K,cnt,S,T;
int r[N],r2[N],t[N],vis[N][N];
int head[N<<1],dep[N<<1], cur[N<<1];
queue<int> q;
void add(int u, int t, int w) {
e[++cnt] = (edge) {t, head[u], w}; head[u] = cnt;
e[++cnt] = (edge) {u, head[t], 0}; head[t] = cnt;
}
void build(int x) {
memset(head, 0, sizeof head); cnt = 1;
for (int i = 1; i <= n; i++) add(S, i, x/t[i]+1);
for (int i = 1; i <= m; i++) add(i+n, T, 1);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) if (vis[i][j]) add(i, j+n, 1);
}
bool bfs() {
memset(dep, 0, sizeof dep);
dep[S] = 1; q.push(S);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = head[u]; i; i = e[i].nxt) {
int t = e[i].t;
if (!dep[t] && e[i].w) dep[t] = dep[u]+1, q.push(t);
}
}
return dep[T] != 0;
}
int dfs(int x, int flow) {
if (x == T) return flow;
for (int &i = cur[x]; i; i = e[i].nxt) {
int t = e[i].t;
if (e[i].w > 0 && dep[t] == dep[x]+1) {
int tmp = dfs(t, min(flow, e[i].w));
if (tmp <= 0) continue;
e[i].w-=tmp; e[i^1].w+=tmp;
return tmp;
}
}
return 0;
}
int dinic() {
int ans = 0;
while (bfs()) {
for (int i = 1; i <= T; i++) cur[i] = head[i];
while (int k = dfs(S, 1e9)) ans+=k;
}
return ans;
}
int main() {
// freopen("1822.in", "r", stdin);
// freopen("1822.out", "w", stdout);
n = read(); m = read(); K = read();
S = n+m+1; T = S+1;
for (int i = 1; i <= n; i++) a[i].x = read(), a[i].y = read(), r[i] = read(), t[i] = read();
for (int i = 1; i <= m; i++) b[i].x = read(), b[i].y = read();
for (int i = 1; i <= K; i++) c[i].x = read(), c[i].y = read(), r2[i] = read();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (dis(a[i], b[j]) > r[i]) continue;
vis[i][j] = 1;
for (int k = 1; k <= K; k++) {
if ((c[k]-a[i])*(b[j]-a[i]) < 0) && dis(a[i], c[k]) >= r2[k]) continue;
if ((c[k]-b[j])*(a[i]-b[j]) < 0 && dis(b[j], c[k]) >= r2[k]) continue;
if (fabs((c[k]-a[i])^(c[k]-b[j]))/dis(a[i], b[j]) >= r2[k]) continue;
vis[i][j] = 0; break;
}
}
int l = 0, r = 4e6+7, ans=-1;
while (l <= r) {
int mid = (l+r)>>1;
build(mid);
if (dinic() == m) r = mid-1, ans = mid;
else l = mid+1;
}
wln(ans);
}