题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1822
题意:WJJ喜欢“魔兽争霸”这个游戏。在 游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵。我们认为,巫妖和小精灵都可以看成是平面上的点。 当巫妖和小精灵之间的直线距离不超过R,且巫妖看到小精灵的视线没有被树木阻挡(也就是说,巫妖和小精灵的连线与任何树木都没有公共点)的话,巫妖就可以 瞬间杀灭一个小精灵。 在森林里有N个巫妖,每个巫妖释放Frozen Nova之后,都需要等待一段时间,才能再次施放。不同的巫妖有不同的等待时间和施法范围,但相同的是,每次施放都可以杀死一个小精灵。 现在巫妖的头目想知道,若从0时刻开始计算,至少需要花费多少时间,可以杀死所有的小精灵?
思路:预处理每个巫妖可以杀死的精灵。之后 二分答案最大流判可行性。但是我觉得这个数据有问题。下面这个预处理是用的别人的。我原来写的是WA。但是我觉得这个预处理是有bug的。他是直接相当于 求树到巫妖和精灵连线的距离小于树的半径。但是我觉得这个不对的。比如巫妖和精灵在树的同一侧。
struct node
{
int v,cap,next;
};
node edges[N*N];
int head[N],e;
void add(int u,int v,int cap)
{
edges[e].v=v;
edges[e].cap=cap;
edges[e].next=head[u];
head[u]=e++;
}
void Add(int u,int v,int cap)
{
add(u,v,cap);
add(v,u,0);
}
int cur[N],h[N],num[N],pre[N];
int Maxflow(int s,int t,int n)
{
int i;
for(i=0;i<=n;i++) h[i]=num[i]=0,cur[i]=head[i];
int u=s,ans=0,Min,k,x;
while(h[u]<n)
{
if(u==t)
{
Min=INF+1;
for(i=s;i!=t;i=edges[cur[i]].v)
{
x=cur[i];
if(edges[x].cap<Min) Min=edges[x].cap,k=i;
}
ans+=Min; u=k;
for(i=s;i!=t;i=edges[cur[i]].v)
{
x=cur[i];
edges[x].cap-=Min;
edges[x^1].cap+=Min;
}
}
for(i=cur[u];i!=-1;i=edges[i].next)
{
if(edges[i].cap>0&&h[u]==1+h[edges[i].v])
{
break;
}
}
if(i!=-1)
{
cur[u]=i;
pre[edges[i].v]=u;
u=edges[i].v;
}
else
{
if(--num[h[u]]==0) break;
cur[u]=head[u];
x=n;
for(i=head[u];i!=-1;i=edges[i].next)
{
k=edges[i].v;
if(edges[i].cap>0&&h[k]<x) x=h[k];
}
h[u]=x+1;
num[x+1]++;
if(u!=s) u=pre[u];
}
}
return ans;
}
struct A
{
int x,y,r,t;
void get()
{
RD(x,y); RD(r,t);
}
};
A a[N];
struct B
{
int x,y;
void get()
{
RD(x,y);
}
};
B b[N];
struct C
{
int x,y,r;
void get()
{
RD(x,y,r);
}
};
C c[N];
int n,m,K;
vector<int> V[N];
int dis(int x,int y)
{
return x*x+y*y;
}
int check(A pa,B pb,C pc)
{
double a=sqrt(dis(pa.x-pb.x,pa.y-pb.y)*1.0);
double b=sqrt(dis(pc.x-pb.x,pc.y-pb.y)*1.0);
double c=sqrt(dis(pa.x-pc.x,pa.y-pc.y)*1.0);
double p=(a+b+c)/2;
double s=sqrt(p*(p-a)*(p-b)*(p-c));
double tmp=a*pc.r/2;
if(tmp>=s) return 0;
return 1;
}
void init()
{
int i,j,k;
FOR1(i,n) FOR1(j,m)
{
if(dis(a[i].x-b[j].x,a[i].y-b[j].y)>a[i].r*a[i].r) continue;
FOR1(k,K) if(!check(a[i],b[j],c[k])) break;
if(k>K) V[i].pb(j);
}
}
int OK(int mid)
{
clr(head,-1); e=0;
int s=0,t=n+m+1,i,j,k;
FOR1(i,n) Add(s,i,mid/a[i].t+1);
FOR1(i,m) Add(n+i,t,1);
FOR1(i,n) FOR0(j,SZ(V[i]))
{
k=V[i][j];
Add(i,n+k,1);
}
return Maxflow(s,t,t+1)==m;
}
int main()
{
RD(n,m,K);
int i,j;
FOR1(i,n) a[i].get();
FOR1(i,m) b[i].get();
FOR1(i,K) c[i].get();
init();
int low=0,high=INF,mid,ans=-1;
while(low<=high)
{
mid=(low+high)>>1;
if(OK(mid)) ans=mid,high=mid-1;
else low=mid+1;
}
PR(ans);
}