【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;
}

 

posted @ 2017-09-19 15:22  Illya  阅读(188)  评论(1编辑  收藏  举报