P3324 [SDOI2015]星际战争 二分 + 网络流

  

为 二分加网络流  二分答案即可

图很好建  注意double型二分的写法。。一开始  1 加  fabs    2 L+一个值  R-一遍

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define pb push_back
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3f
const int N=1e4+44;
const int M=1e4+54;
double eps=1e-4;
int d[N];
struct edge {
    int to, next;double w;
} e[M << 1];
int head[N],cur[N],cnt = 1;
void add(int x, int y, double z) {
    e[++cnt] = (edge){y, head[x], z};
    head[x] = cnt;
    e[++cnt] = (edge){x, head[y], 0};
    head[y] = cnt;
}
void init()
{   
    rep(i,0,cnt)head[i]=0;
    cnt=1;
}
int level[N];
bool bfs(int s, int t) {
    memset(level, 0, sizeof level);
    queue<int> q;
    level[s] = 1;
    q.push(s);
    while (!q.empty()) {
        int pos = q.front();q.pop();
        for (int i = head[pos]; i; i = e[i].next) {
            int nx = e[i].to;
            if (!e[i].w || level[nx]) continue;
            level[nx] = level[pos] + 1;
            q.push(nx);
        }
    }
    return level[t];
}
double dfs(int s, int t, double flow) {
    if(s==t||flow==0)return flow;
    double f,ret = 0;
    for (int &i = cur[s],v; i; i = e[i].next) {
         v = e[i].to;
        if (level[v] == level[s] + 1 && (f=dfs(v,t,min(flow,e[i].w)))>0) {
            e[i].w -= f;
            e[i ^ 1].w += f;
            flow -= f;
            ret += f;
            if(!flow)break;
        }
    }
    return ret;
}
double dinic(int s, int t) {
    double ret = 0.0;
    while (bfs(s, t)) memcpy(cur,head,sizeof cur),ret += dfs(s, t, inf);
    return ret;
}
int n,m,s,t,a,b,c,S,T;
int hp[N],attack[N],sum,mp[100][100];

bool check(double  mid)
{   
    init();
    rep(i,1,n)add(i,t,1.0*hp[i]);
    rep(i,1,m)
    {
        add(s,i+n,1.0*mid*attack[i]);
        rep(j,1,n)
        {   
            if(mp[i][j])
            add(i+n,j,1.0*inf);
        }
    }
    double ans=dinic(s,t);
    return fabs(ans-1.0*sum)<=eps;
}

int main()
{
    scanf("%d%d",&n,&m);s=n+m+1,t=s+1;
    rep(i,1,n)scanf("%d",&hp[i]),sum+=hp[i];
    rep(i,1,m)scanf("%d",&attack[i]);
    rep(i,1,m)rep(j,1,n)scanf("%d",&mp[i][j]);
    double L=0,R=1000000,ans=0;
    while(R-L>=0.001)
    {   
        double mid=(L+R)/2;
        if(check(mid))R=mid,ans=mid;
        else L=mid; 
    }
    printf("%.6f",ans);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/bxd123/p/11493056.html