BZOJ3993 SDOI2015 星际战争 二分法+网络流

题意:有N个机器人护甲分别为ai,M个武器攻击力分别为bi/s,每个武器可以攻击的机器人不同,求摧毁所有机器人的最短时间,时间可以为小数

题解:实数上二分答案。好久没写网络流都不会开空间了……

#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define U 500000.0
#define eps 1e-6
#define S 0
#define T N+M+1

const int MAXN=50+2;
const int MAXE=1000100+2;
struct Hash{
    int u;
    Hash *Next;
}*Tab[2*MAXN],Mem[MAXE],*Cur[2*MAXN];
struct Edge{
    int u;
    double c;
}e[MAXE];
int N,M,cnt,d[2*MAXN];
double a[MAXN],b[MAXN],s;
bool Can[MAXN][MAXN];
queue<int> q;

void Insert(int u,int v,double c){
    Mem[cnt].u=cnt,Mem[cnt].Next=Tab[u],e[cnt].u=v,e[cnt].c=c,Tab[u]=&Mem[cnt++];
    Mem[cnt].u=cnt,Mem[cnt].Next=Tab[v],e[cnt].u=u,e[cnt].c=0,Tab[v]=&Mem[cnt++];
}

bool BFS(int s,int t){
    memset(d,-1,sizeof(d));
    d[s]=0,q.push(s);

    int x;
    while(!q.empty()){
        x=q.front(),q.pop();
        for(Hash *p=Tab[x];p;p=p->Next){
            if(e[p->u].c>eps && d[e[p->u].u]==-1)
                d[e[p->u].u]=d[x]+1,q.push(e[p->u].u);
        }
    }
    return d[t]>0;
}

double DFS(int x,double f,int t){
    if(x==t) return f;

    double used=0,flow;
    for(Hash *p=Cur[x];p;p=p->Next)
        if(e[p->u].c>eps && d[e[p->u].u]==d[x]+1){
            flow=DFS(e[p->u].u,min(e[p->u].c,f-used),t);
            e[p->u].c-=flow,e[p->u^1].c+=flow,used+=flow;
            if(e[p->u].c>eps) Cur[x]=p;
            if(f-used<eps) return f;
        }

    if(used==0) d[x]=-1;
    return used;
}

double Dinic(int s,int t){
    double Ret=0;
    while(BFS(s,t)){
        memcpy(Cur,Tab,sizeof(Cur));
        Ret+=DFS(s,U,t);
    }
    return Ret;
}

int main(){
    scanf("%d %d",&N,&M);
    for(int i=1;i<=N;i++) scanf("%lf",a+i),s+=a[i];
    for(int i=1;i<=M;i++) scanf("%lf",b+i);

    for(int i=1;i<=M;i++)
        for(int j=1,t;j<=N;j++)
            scanf("%d",&t),Can[i][j]=t;

    double l=0,r=U,m;
    while(r-l>eps){
        m=(l+r)/2,cnt=0;
        memset(Tab,0,sizeof(Tab));

        for(int i=1;i<=M;i++){
            Insert(S,i,b[i]*m);
            for(int j=1;j<=N;j++)
                if(Can[i][j]) Insert(i,M+j,U);
        }
        for(int i=1;i<=N;i++) Insert(M+i,T,a[i]);

        if(fabs(Dinic(S,T)-s)<eps) r=m;
        else l=m;
    }
    printf("%lf",m);

    return 0;
}
View Code

 

posted @ 2017-03-03 23:53  WDZRMPCBIT  阅读(138)  评论(0编辑  收藏  举报