洛谷P3324 [SDOI2015]星际战争 题解

题目链接:

https://www.luogu.org/problemnew/show/P3324

分析:

因为本题的时间<stron>较多,不能枚举,但发现有单调性,于是二分答案,二分使用的时间 T T T</stron>

每个攻击装置造成的伤害总量已知,为 T B i T*B_i TBi,现在有了伤害总量、生命总量,如何判断在 T T T时间内,机器人是否被全部打死?

源点S向所有攻击装置连边,流量为 T B i T*B_i TBi

攻击装置向能攻击到的机器人连边,流量为INF

所有机器人向汇点T连边,流量为 A i A_i Ai

验证 T T T时间所有机器人都能被打死 当且仅当 上图的最大流 = A i = \sum A_i =Ai(所有机器人生命值之和)

代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#define maxn 110
#define inf 0x7fffffffffffffffll
using namespace std;
int n,m,s,t,d[maxn];
long long sum,ans,Sum_A;
long long a[maxn];
long long b[maxn];
int mp[maxn][maxn];
struct edge
{
    int to,rev;
    long long val;
    edge (int _to,long long _val,int _rev)
    {
        to=_to;
        val=_val;
        rev=_rev;
    }
};
vector<edge> e[maxn];
void add(int x,int y,long long val)
{
    e[x].push_back(edge(y,val,e[y].size()));
    e[y].push_back(edge(x,0,e[x].size()-1));
}
bool bfs()
{
    memset(d, -1, sizeof(d));
    queue<int> q;
    q.push(s);
    d[s]=0;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(int i=0;i<e[x].size();i++)
        {
            int y=e[x][i].to;
            if(d[y]==-1 && e[x][i].val)
            {
                q.push(y);
                d[y]=d[x]+1;
            }
        }
    }
    if(d[t]==-1)
        return 0;
    else
        return 1;
}
long long dfs(int x,long long low) 
{
    if(x==t||low==0)
        return low;
    long long totflow=0;
    for(int i=0;i<e[x].size();i++)
    {
        int y=e[x][i].to;
        int rev=e[x][i].rev;
        if(d[y]==d[x]+1&&e[x][i].val) 
        {
            long long a=dfs(y,min(low,e[x][i].val)); 
            e[x][i].val-=a;
            e[y][rev].val+=a;
            low-=a;
            totflow+=a;
            if(low==0) 
                return totflow;
        }
    }
    if(low!=0) 
        d[x]=-1;
    return totflow;
}
bool pd(long long Time)
{
    for(int i=0;i<maxn;i++)
        e[i].clear();
    sum=ans=0;
    s=0,t=n+m+1;
    for(int i=1;i<=m;i++)
        add(s,i,Time*b[i]);
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
            if(mp[i][j])
                add(i,j+m,inf);
    for(int j=1;j<=n;j++)
        add(j+m,t,a[j]*10000);
    while(bfs())
    {
    	ans+=dfs(s,inf);
    }
    if(ans==Sum_A*10000)
        return 1;
    else
        return 0;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        Sum_A+=a[i];
    }
    for(int i=1;i<=m;i++)
        scanf("%lld",&b[i]);
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&mp[i][j]);
    long long l=0,r=10000000000000ll;
    long long an=l;
    while(l<=r)
    {
        long long mid=(l+r)/2;
        if(pd(mid))
        {
            an=mid;
            r=mid-1;
        }
        else
            l=mid+1;
    }
    printf("%.6lf\n",(double)an/(double)10000.0);
    return 0;
}
全部评论

相关推荐

把球:这个听过,你加了就会发现是字节的hr
点赞 评论 收藏
分享
ProMonkey2024:5个oc?厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了(别的帖子偷来的,现学现卖😋)
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务