【bzoj1822】冷冻波
计算几何找出巫妖可以攻击的小精灵
二分时间网络流判定
#include<bits/stdc++.h> #define maxn 405 #define maxm 80005 #define INF 0x7f7f7f7f using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } struct scsc{ int next,to,w; }edge[maxm<<1]; int n,m,k,Len,head[maxn<<1],cur[maxn<<1],h[maxn<<1],r[maxn],cd[maxn],range[maxn],vis[maxn],atk[maxn][maxn]; void addedge(int u,int v,int w){ edge[++Len].to=v;edge[Len].next=head[u];edge[Len].w=w;head[u]=Len; edge[++Len].to=u;edge[Len].next=head[v];edge[Len].w=0;head[v]=Len; } struct P{ int x,y; }Lich[maxn],Elf[maxn],Tree[maxn]; struct L{ P a,b; L(P a,P b):a(a),b(b){}; L(){}; }; inline P operator-(P a,P b){ P t;t.x=a.x-b.x;t.y=a.y-b.y;return t; } inline double operator*(P a,P b){ return a.x*b.y-a.y*b.x; } inline double dot(P a,P b){ return a.x*b.x+a.y*b.y; } inline double dis(P a,P b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } inline double dis(L l,P p){ if(dot(l.a-p,l.b-p)>0) return min(dis(l.a,p),dis(l.b,p)); return abs((p-l.a)*(l.b-l.a)/dis(l.a,l.b)); } bool jug(P a,P b){ for(int i=1;i<=k;i++) if(dis(L(a,b),Tree[i])<1.0*r[i])return 0; return 1; } int bfs(int s,int t){ queue<int>Q; memset(h,-1,sizeof(h)); Q.push(s);h[s]=0; while(!Q.empty()){ int u=Q.front();Q.pop(); for(int i=head[u];i;i=edge[i].next){ int v=edge[i].to; if(edge[i].w&&h[v]==-1){ Q.push(v); h[v]=h[u]+1; } } } return h[t]!=-1; } int dfs(int u,int f,int t){ if(u==t)return f; int used=0,w; for(int i=cur[u];i&&used<f;i=edge[i].next){ int v=edge[i].to; if(edge[i].w&&h[v]==h[u]+1){ w=dfs(v,min(edge[i].w,f-used),t); edge[i].w-=w; edge[i^1].w+=w; used+=w; if(edge[i].w)cur[u]=i; } } if(!used)h[u]=INF; return used; } int dinic(int s,int t){ int ret=0; while(bfs(s,t)){ for(int i=s;i<=t;++i)cur[i]=head[i]; ret+=dfs(s,INF,t); } return ret; } int check(int t){ int S=0,T=n+m+1; Len=1;memset(head,0,sizeof(head)); for(int i=1;i<=n;++i)addedge(S,i,t/cd[i]+1); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(atk[i][j])addedge(i,n+j,1); for(int i=1;i<=m;++i)addedge(n+i,T,1); return dinic(S,T)==m; } int main(){ n=read();m=read();k=read();int mx=0; for(int i=1;i<=n;++i){ Lich[i].x=(double)read();Lich[i].y=(double)read(); range[i]=read();cd[i]=read(); if(cd[i]>mx)mx=cd[i]; } for(int i=1;i<=m;++i){ Elf[i].x=(double)read();Elf[i].y=(double)read(); } for(int i=1;i<=k;++i){ Tree[i].x=(double)read();Tree[i].y=(double)read(); r[i]=read(); } for(int i=1;i<=n;++i) for(int j=1;j<=m;++j){ if(dis(Lich[i],Elf[j])>1.0*range[i])continue; atk[i][j]=jug(Lich[i],Elf[j]); if(atk[i][j])vis[j]=1; } for(int i=1;i<=m;++i)if(!vis[i]){ puts("-1"); return 0; } int l=0,r=m*mx; while(l<=r){ int mid=l+r>>1; if(check(mid))r=mid-1; else l=mid+1; } printf("%d\n",l); return 0; }