题意:有n个巫妖,m个精灵,k棵树,他们都有自己的位置坐标表示。巫妖有冷却时间和范围。树有覆盖范围。
假设某个巫妖攻击精灵的路线(他俩之间的连线)经过树的覆盖范围,表示精灵被树挡住巫妖攻击不到。求巫妖杀死所有精灵的最少的时间。若无法所有杀死输出-1;
巫妖能否打到精灵用线段与圆是否相交来推断,若相交,就攻击不到。
由于时间越长攻击的精灵越多,所以时间可以用二分解决。
二分出一个时间,然后建图,用最大流跑,结果如果等于m则时间可以再小。
直到结果不等于m
建图的时候源点连接 精灵,精灵连接巫妖,巫妖连接汇点,
这样的好处是,精灵可以被女巫杀死,而女巫的杀伤力由二分的时间来决定,就是 时间/冷却时间 + 1
交了很多次,一直wa,一直wa,wa到爆炸,到最后改了精度,竟然过了,caodan!!浪费感情
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#define ll long long
#define INF 0x3f3f3f3f
const int maxn = 1e6+5;
const double eps=1e-7;//注意精度
using namespace std;
struct node1 {
int to;
int cap;
int rev;
node1(){}
node1(int a,int b,int d):to(a),cap(b),rev(d){}
};
vector<node1> v[maxn];
int d[maxn],cur[maxn];
struct Point {
double x,y;
};
struct Lich {
Point p;
double r;
int t;
}lich[maxn];
struct Node {
Point p;
}node[maxn];
struct Tree {
Point p;
double r;
}tree[maxn];
double Distance(Point a, Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)*1.0 + 1.0*(a.y-b.y)*(a.y-b.y));
}
double xmult(Point p1, Point p2, Point p)
{
return (p1.x-p.x)*(p2.y-p.y) - (p2.x-p.x)*(p1.y-p.y);
}
double disptoseg(Point p, Point a ,Point b)
{
Point t = p;
t.x += a.y-b.y, t.y += b.x-a.x;
if(xmult(a,t,p)*xmult(b,t,p)>eps)
return Distance(p,a) < Distance(p,b)? Distance(p,a) : Distance(p,b);
return fabs(xmult(p, a, b))/Distance(a, b);
}
int T,n,m,k,s,t,ans,mp[205][205];
void init(){
memset(mp,0,sizeof(mp));
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++) {
if(Distance(lich[j].p,node[i].p)<=lich[j].r){
int flag=1;
for(int l=1;l<=k;l++) {
if(disptoseg(tree[l].p,node[i].p,lich[j].p)<=tree[l].r) {
flag=0;
break;
}
}
if(flag) {
mp[i][j]=1;
}
}
}
}
void addedge(int from,int to,int cap) {
v[from].push_back(node1(to,cap,v[to].size()));
v[to].push_back(node1(from,0,v[from].size()-1));
}
int dfs(int u,int flow) {
if(u==t || !flow) return flow;
int ans = 0;
for(int &i = cur[u];i<v[u].size();i++) {
node1 &e = v[u][i];
if(d[e.to] == d[u] + 1 && e.cap > 0) {
int temp = dfs(e.to,min(flow,e.cap));
if(temp>0) {
flow-=temp;
e.cap-=temp;
v[e.to][e.rev].cap+=temp;
ans += temp;
if(!flow) break;
}
}
}
if(!ans) d[u] = -1;
return ans;
}
bool bfs() {
for(int i=0;i<=t+12;i++) d[i] = -1;
queue<int> q;
q.push(s);
d[s] = 0;
while(!q.empty()) {
int u = q.front();
q.pop();
for(int i=0;i<v[u].size();i++) {
int to = v[u][i].to;
if(d[to]==-1 && v[u][i].cap>0) {
d[to] = d[u] + 1;
q.push(to);
}
}
}
return (d[t] != -1);
}
int dinic() {
int max_flow = 0,tt;
while(bfs()) {
for(int i=s;i<=t+12;i++) cur[i] = 0;
while((tt = dfs(s,INF)) > 0) max_flow+=tt;
}
return max_flow;
}
void getmap(int mid) {
s = 0,t = n+m+1;
for(int i=s;i<=t;i++)v[i].clear();
for(int i=1;i<=m;i++) {
addedge(s,i,1);
}
for(int i=1;i<=n;i++) {
addedge(i+m,t,mid/lich[i].t+1);
}
for(int i=1;i<=m;i++) {
for(int j=1;j<=n;j++) {
if(mp[i][j]) {
addedge(i,j+m,1);
}
}
}
}
int solve(int mid) {
getmap(mid);
return dinic();
}
int main()
{
scanf("%d",&T);
while(T--) {
scanf("%d%d%d",&n,&m,&k);
int minn=0;
for(int i=1;i<=n;i++) scanf("%lf%lf%lf%d",&lich[i].p.x,&lich[i].p.y,&lich[i].r,&lich[i].t),minn=min(minn,lich[i].t);
for(int i=1;i<=m;i++) scanf("%lf%lf",&node[i].p.x,&node[i].p.y);
for(int i=1;i<=k;i++) scanf("%lf%lf%lf",&tree[i].p.x,&tree[i].p.y,&tree[i].r);
init();
int l=0,r=m*minn+100;
int mid,ans=-1;
while(l<=r) {
mid = r+l>>1;
int temp = solve(mid);
if(temp==m) {
r = mid - 1;
ans = mid;
}
else
l = mid + 1;
}
printf("%d\n",ans);
}
return 0;
}