星际战争 HYSBZ - 3993

https://www.lydsy.com/JudgeOnline/problem.php?id=3993

二分时间t 看规定时间内能否消灭全部机器人 sss(大源点)向ss(小源点)连权值为sum(a[1]+a[2]+...+a[n])的边 ss向m个炮塔连b[i]*t的边 m个炮塔向n个机器人连b[i]*t的边 n个机器人向汇点连a[i]的边

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const double N=1000000000.0;
const double eps=1e-8;;
const int maxn=1e2+10;
const int maxm=1e5+10;

struct node
{
    double w;
    int v,next;
};

queue <int> que;
node edge[maxm];
double a[maxn],b[maxn];
double sum;
int e[maxn][maxn];
int first[maxn],dis[maxn],gap[maxn],cur[maxn],pre[maxn];
int n,m,num,sss,ss,eee;

void addedge(int u,int v,double w)
{
    edge[num].v=v;
    edge[num].w=w;
    edge[num].next=first[u];
    first[u]=num++;

    edge[num].v=u;
    edge[num].w=0;
    edge[num].next=first[v];
    first[v]=num++;
}

void bfs()
{
    int i,u,v;
    while(!que.empty()) que.pop();
    memset(dis,-1,sizeof(dis));
    memset(gap,0,sizeof(gap));
    que.push(eee);
    dis[eee]=0;
    gap[0]++;
    while(!que.empty()){
        u=que.front();
        que.pop();
        for(i=first[u];i!=-1;i=edge[i].next){
            v=edge[i].v;
            if(dis[v]==-1){
                que.push(v);
                dis[v]=dis[u]+1;
                gap[dis[v]]++;
            }
        }
    }
}

double isap()
{
    double w,flow,ans;
    int j,u,v,minn;
    bfs();
    memcpy(cur,first,sizeof(first));
    memset(pre,-1,sizeof(pre));
    u=sss,flow=N,ans=0.0;
    while(dis[sss]<num){
        int &i=cur[u];
        for(;i!=-1;i=edge[i].next){
            v=edge[i].v,w=edge[i].w;
            if(dis[v]+1==dis[u]&&w>0.0){
                pre[v]=i;
                u=v,flow=min(flow,w);
                if(u==eee){
                    while(u!=sss){
                        edge[pre[u]].w-=flow;
                        edge[pre[u]^1].w+=flow;
                        u=edge[pre[u]^1].v;
                    }
                    //printf("*%.2f*\n",flow);
                    ans+=flow,flow=N;
                }
                break;
            }
        }
        if(i==-1){
            if(--gap[dis[u]]==0) break;
            cur[u]=first[u];
            minn=num-1;
            for(j=first[u];j!=-1;j=edge[j].next){
                v=edge[j].v,w=edge[j].w;
                if(w>0.0){
                    minn=min(minn,dis[v]);
                }
            }
            dis[u]=minn+1;
            gap[dis[u]]++;
            if(u!=sss) u=edge[pre[u]^1].v;
        }
    }
    return ans;
}

bool judge(double lim)
{
    double res;
    int i,j;
    sss=n+m+1,ss=n+m+2,eee=n+m+3;
    memset(first,-1,sizeof(first));
    num=0;

    addedge(sss,ss,sum*lim);

    for(i=1;i<=m;i++){
        addedge(ss,i,b[i]*lim);
    }

    for(i=1;i<=m;i++){
        for(j=1;j<=n;j++){
            if(e[i][j]){
                addedge(i,m+j,b[i]*lim);
            }
        }
    }

    for(i=m+1;i<=m+n;i++){
        addedge(i,eee,a[i-m]);
    }

    num=n+m+3;
    res=isap();
    //printf("%.2f\n",res);
    if(res>=sum) return 1;
    else return 0;
}

double solve()
{
    double res,l,r,mid;

    l=0.0,r=100000.0;
    while(r-l>eps){
        mid=(l+r)/2.0;
        if(judge(mid)) r=mid,res=mid;
        else l=mid;
    }

    //judge(1.3);
    return res;
}

int main()
{
    int i,j;
    scanf("%d%d",&n,&m);
    sum=0.0;
    for(i=1;i<=n;i++){
        scanf("%lf",&a[i]);
        sum+=a[i];
    }
    for(i=1;i<=m;i++){
        scanf("%lf",&b[i]);
    }
    for(i=1;i<=m;i++){
        for(j=1;j<=n;j++){
            scanf("%d",&e[i][j]);
        }
    }
    printf("%.6f\n",solve());
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/88617426