题意:有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;
}