• 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;
    }
     
  • 相关阅读:
    POJ2182Lost Cows
    BZOJ4003: [JLOI2015]城池攻占
    POJ1635Subway tree systems
    BZOJ1005: [HNOI2008]明明的烦恼
    POJ1182 NOI2001 食物链
    栈的链式实现
    栈的数组实现
    链表ADT的实现
    #ifndef的用法
    using namespace std
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/6882642.html
Copyright © 2020-2023  润新知