BZOJ 3993: [SDOI2015]星际战争

二次联通门 : BZOJ 3993: [SDOI2015]星际战争

 

 

 

 

/*
    BZOJ 3993: [SDOI2015]星际战争
    
    之前总是TLE
    结果改了改Max的值就过了...
    
    最大流
    
    二分时间
    源点与武器连边
    装甲与汇点连边
    武器再与装甲连边
    把 时间 * 攻击作为边权,跑最大流
    判断最后的流是否大于装甲的总和  
*/
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

#define Max 101
#define EPS 0.0001
#define INF 1e7

using namespace std;

void read (int &now)
{
    now = 0;
    char word = getchar ();
    while (word < '0' || word > '9')
        word = getchar ();
    while (word >= '0' && word <= '9')
    {
        now = now * 10 + word - '0';
        word = getchar ();
    }
}

int deep[Max << 2];

int N, M;
int S, T = (Max << 2) - 1;
int armor[Max];
int fight[Max];
int Sum;
int Total;
int map[Max][Max];

int Edge_Count;
int edge_list[Max << 2];

struct Edge
{
    int to;
    double flow;
    int next;
}edge[(Max * Max) << 1];

inline void AddEdge (int from, int to, double flow)
{
    Edge_Count++;
    edge[Edge_Count].to = to;
    edge[Edge_Count].next = edge_list[from];
    edge[Edge_Count].flow = flow;
    edge_list[from] = Edge_Count;
    Edge_Count++;
    edge[Edge_Count].to = from;
    edge[Edge_Count].flow = 0;
    edge[Edge_Count].next = edge_list[to];
    edge_list[to] = Edge_Count;
}

double min (double a, double b)
{
    return a < b ? a : b;
}

double Flowing (int now, double flow)
{
    if (now == T || flow == 0)
        return flow;
    double res = 0, pos;
    for (int i = edge_list[now]; i; i = edge[i].next)
    {
        if (deep[edge[i].to] != deep[now] + 1 || edge[i].flow <= 0)
            continue;
        pos = Flowing (edge[i].to, min (edge[i].flow, flow));
        if (pos > 0)
        {
            flow -= pos;
            res += pos;
            edge[i].flow -= pos;
            edge[i ^ 1].flow += pos;
            if (flow == 0)
                return res;
        }
    }
    if (res == 0)
        deep[now] = -1;
    return res;
}

bool Bfs ()
{
    memset (deep, -1, sizeof deep);
    queue <int> Queue;
    deep[S] = 0;
    Queue.push (S); 
    int now;
    while (!Queue.empty ())
    {
        now = Queue.front ();
        Queue.pop ();
        for (int i = edge_list[now]; i; i = edge[i].next)
            if (deep[edge[i].to] < 0 && edge[i].flow > 0)
            {
                deep[edge[i].to] = deep[now] + 1;
                if (edge[i].to == T)
                    return true;
                Queue.push (edge[i].to); 
            }
    }
    return false;
}

bool Check (double Time)
{
    double Answer = 0;
    Edge_Count = 1;
    memset (edge_list, 0, sizeof edge_list);
    for (int i = 1; i <= M; i++)
        AddEdge (S, i, fight[i] * Time);
    for (int i = 1; i <= N; i++)
        AddEdge (i + M, T, armor[i]);
    for (int i = 1; i <= M; i++)
        for (int j = 1; j <= N; j++)
            if (map[i][j])
                AddEdge (i, j + M, INF);
    while (Bfs ())
        Answer += Flowing (S, INF);
    return Answer >= (double)Sum - EPS;
}

int main (int argc, char *argv[])
{
    read (N);
    read (M);
    for (int i = 1; i <= N; i++)
    {
        read (armor[i]);
        Sum += armor[i];
    }
    for (int i = 1; i <= M; i++)
    {
        read (fight[i]);
        Total += fight[i];
    }
    for (int i = 1; i <= M; i++)
        for (int j = 1; j <= N; j++)
            read (map[i][j]);
    double l = (double)Sum / (double)Total, r = 10000.00;
    double Answer = 0;
    double Mid;
    while (l < r)
    {
        Mid = (l + r) / 2.0;
        if (Check (Mid))
        {
            r = Mid - EPS;
            Answer = Mid;
        }
        else
            l = Mid + EPS;
    }
    printf ("%lf", Answer);
    return 0;
}
 

 

posted @ 2017-05-20 17:31  ZlycerQan  阅读(171)  评论(0编辑  收藏  举报