BZOJ 3994 (思路最大流)

因为用时可以二分,所以先二分最小值,那么判断用最大流就可以了。

好像不用解释什么,对于源点对每个装备连一条边,边权为时间*装备杀伤力,经过可行性矩阵 ,流向n个机器人,每个机器人向汇点流自己的防御值。

那么如果最大流等于所有机器人防御值之和,那么最大流方案,既是该时间下的可行性方案。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ALL(a) a.begin(), a.end()
#define clr(a, x) memset(a, x, sizeof a)
#define X first
#define Y second
#define pb push_back
#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define rep1(i,x,y) for(int i=x;i<=y;i++)
#define rep(i,n) for(int i=0;i<(int)n;i++)
using namespace std;
const double eps = 1e-6;
typedef long long LL;
typedef long long ll;
typedef pair pii;
const int oo =0x3f3f3f3f;

const int maxn = 120;
struct Edge
{
    int u, v;
    double cap,flow;
    Edge(int u, int v, double c, double f):u(u), v(v), cap(c), flow(f) {}
};

struct Dinic
{
    int n, m, s, t, cur[maxn];
    int d[maxn];
    bool vis[maxn];
    vector edge;
    vector G[maxn];
    void init(int n)
    {
        this->n=n;
        for(int i=0; i<=n; i++)
            G[i].clear();
        edge.clear();
    }
    int AddEdge(int u, int v, double c)
    {
        edge.push_back(Edge(u, v, c, 0));
        edge.push_back(Edge(v, u, 0, 0));
        m=edge.size();
        G[u].push_back(m-2);
        G[v].push_back(m-1);
        return m-2;
    }
    bool bfs()
    {
        clr(vis, 0);
        queue q;
        q.push(s);
        d[s]=0, vis[s]=1;
        while(!q.empty())
        {
            int x=q.front();
            q.pop();
            for(int i=0; ie.flow)
                {
                    vis[e.v]=1;
                    d[e.v]=d[x]+1;
                    q.push(e.v);
                }
            }
        }
        return vis[t];
    }
    double dfs(int x, double a)
    {
        if(x==t || a0)
            {
                e.flow+=f;
                edge[G[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(as=s;
        this->t=t;
        double flow=0;
        while(bfs())
        {
            clr(cur, 0);
            flow+=dfs(s, oo);
        }
        return flow;
    }
} net;
int S,T;
int n,m,a[maxn],b[maxn],ma[maxn][maxn];
double all;
int judge(double te){
   net.init(T);
   rep1(i,1,n) net.AddEdge(m+i,T,(double)a[i]);
   rep1(i,1,m) rep1(j,1,n){
       int x=ma[i][j];
       if(x) net.AddEdge(i,m+j,(double)oo);
   }
   for(int i=1;i<=m;i++) net.AddEdge(S,i,te*b[i]);
   return fabs(net.MaxFlow(S,T)-all) eps){
       double mid = (l+r)/2.0;
       if(judge(mid)) r = mid;
       else l = mid;
   }
   printf("%.6lf\n",l);
   return 0;
}


你可能感兴趣的:(网络流)