IndiaHacks 2016 - Online Edition (Div. 1 + Div. 2) D. Delivery Bears 二分+网络流(循环写二分,否则T。。。)

来源:互联网 发布:淘宝交换笔记本主板的 编辑:程序博客网 时间:2024/05/16 23:42

题意

给一个图,每个边有边权,然后有x只熊,每个熊都要背负一样重量的货物,每头熊通过一条路径到i,每条边被所有熊经过的次数乘于货物重量不能大于边权,然后问你最大的货物总重量是多少

每只熊都必须要用,每个熊背负的货物重量一致,所以等价于求每只熊背负的货物的最大重量

题解:

比较显然的是二分+最大流

然后每条边的cap就是该边的边权除以你二分的答案值。

然后跑一发最大流check是否满流就好了。

现在有一个问题就是cap会爆int,其实这时候只用和x取个min就好了。

#include <set>#include <map>#include <stack>#include <queue>#include <deque>#include <cmath>#include <vector>#include <string>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define L(i) i<<1#define R(i) i<<1|1#define INF  0x3f3f3f3f#define pi acos(-1.0)#define eps 1e-12#define maxn 1000100#define MOD 1000000007const int MAXN = 100010;const int MAXM = 400010;struct Edge{    int to,next,cap,flow;} edge[MAXM];int tot,n,m,k;int head[MAXN];int gap[MAXN],dep[MAXN];int pre[MAXN],cur[MAXN];void init(){    tot = 0;    memset(head,-1,sizeof(head));}void add_edge(int u,int v,int w,int rw = 0){    edge[tot].to = v;    edge[tot].cap = w;    edge[tot].flow = 0;    edge[tot].next = head[u];    head[u] = tot++;    edge[tot].to = u;    edge[tot].cap = rw;    edge[tot].flow = 0;    edge[tot].next = head[v];    head[v] = tot++;}int sap(int start,int en,int N){    memset(gap,0,sizeof(gap));    memset(dep,0,sizeof(dep));    memcpy(cur,head,sizeof(head));    int u = start;    pre[u] = -1;    gap[0] = N;    int ans = 0;    while(dep[start] < N)    {        if(u == en)        {            int Min = INF;            for(int i = pre[u]; i != -1; i = pre[edge[i^1].to])                if(Min > edge[i].cap - edge[i].flow)                    Min = edge[i].cap - edge[i].flow;            for(int i = pre[u]; i != -1; i = pre[edge[i^1].to])            {                edge[i].flow += Min;                edge[i^1].flow -= Min;            }            u = start;            ans += Min;            continue;        }        int flag = 0;        int v;        for(int i = cur[u]; i != -1; i = edge[i].next)        {            v = edge[i].to;            if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u])            {                flag = 1;                cur[u] = pre[v] = i;                break;            }        }        if(flag)        {            u = v;            continue;        }        int Min = N;        for(int i = head[u]; i != -1; i = edge[i].next)            if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)            {                Min = dep[edge[i].to];                cur[u] = i;            }        gap[dep[u]]--;        if(!gap[dep[u]])            return ans;        dep[u] = Min + 1;        gap[dep[u]]++;        if(u != start)            u = edge[pre[u]^1].to;    }    return ans;}int x[550],y[550],z[550];int solve(double mid){    init();    for(int i = 0; i < m; i++)        add_edge(x[i],y[i],min(1.0*k,z[i]/(mid)));    add_edge(0,1,k);    add_edge(n,n+1,k);    return sap(0,n+1,n+2) == k;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int t,C = 1;    //scanf("%d",&t);    while(scanf("%d%d%d",&n,&m,&k) != EOF)    {        for(int i = 0; i < m; i++)            scanf("%d%d%d",&x[i],&y[i],&z[i]);        double l = 0,r = maxn;        for(int i = 0; i < 70; i++)        {            double mid = (l + r) / 2;            if(solve(mid))                l = mid;            else                r = mid - eps;        }        printf("%f\n",l*k);    }    return 0;}


0 0
原创粉丝点击