IndiaHacks 2016 - Online Edition (Div. 1 + Div. 2) D. Delivery Bears 二分+网络流

D. Delivery Bears

题目连接:

http://www.codeforces.com/contest/653/problem/D

Description

Niwel is a little golden bear. As everyone knows, bears live in forests, but Niwel got tired of seeing all the trees so he decided to move to the city.

In the city, Niwel took on a job managing bears to deliver goods. The city that he lives in can be represented as a directed graph with n nodes and m edges. Each edge has a weight capacity. A delivery consists of a bear carrying weights with their bear hands on a simple path from node 1 to node n. The total weight that travels across a particular edge must not exceed the weight capacity of that edge.

Niwel has exactly x bears. In the interest of fairness, no bear can rest, and the weight that each bear carries must be exactly the same. However, each bear may take different paths if they like.

Niwel would like to determine, what is the maximum amount of weight he can deliver (it’s the sum of weights carried by bears). Find the maximum weight.

Input

The first line contains three integers n, m and x (2 ≤ n ≤ 50, 1 ≤ m ≤ 500, 1 ≤ x ≤ 100 000) — the number of nodes, the number of directed edges and the number of bears, respectively.

Each of the following m lines contains three integers ai, bi and ci (1 ≤ ai, bi ≤ n, ai ≠ bi, 1 ≤ ci ≤ 1 000 000). This represents a directed edge from node ai to bi with weight capacity ci. There are no self loops and no multiple edges from one city to the other city. More formally, for each i and j that i ≠ j it’s guaranteed that ai ≠ aj or bi ≠ bj. It is also guaranteed that there is at least one path from node 1 to node n.

Output

Print one real value on a single line — the maximum amount of weight Niwel can deliver if he uses exactly x bears. Your answer will be considered correct if its absolute or relative error does not exceed 10 - 6.

Namely: let’s assume that your answer is a, and the answer of the jury is b. The checker program will consider your answer correct if .

Sample Input

4 4 3
1 2 2
2 4 1
1 3 1
3 4 2

Sample Output

1.5000000000

Hint

题意

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

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

题解:

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

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

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

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

代码

 #include<bits/stdc++.h>
using namespace std;

const int MAXN=100000,MAXM=100000,inf=1e9;
struct Edge
{
    int v,c,f,nx;
    Edge() {}
    Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
} E[MAXM];
int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],N,sz;
void init(int _n)
{
    N=_n,sz=0; memset(G,-1,sizeof(G[0])*N);
}
void link(int u,int v,int c)
{
    E[sz]=Edge(v,c,0,G[u]); G[u]=sz++;
    E[sz]=Edge(u,0,0,G[v]); G[v]=sz++;
}

bool bfs(int S,int T)
{
    static int Q[MAXN]; memset(dis,-1,sizeof(dis[0])*N);
    dis[S]=0; Q[0]=S;
    for (int h=0,t=1,u,v,it;h<t;++h)
    {
        for (u=Q[h],it=G[u];~it;it=E[it].nx)
        {
            if (dis[v=E[it].v]==-1&&E[it].c>E[it].f)
            {
                dis[v]=dis[u]+1; Q[t++]=v;
            }
        }
    }
    return dis[T]!=-1;
}
int dfs(int u,int T,int low)
{
    if (u==T) return low;
    int ret=0,tmp,v;
    for (int &it=cur[u];~it&&ret<low;it=E[it].nx)
    {
        if (dis[v=E[it].v]==dis[u]+1&&E[it].c>E[it].f)
        {
            if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
            {
                ret+=tmp; E[it].f+=tmp; E[it^1].f-=tmp;
            }
        }
    }
    if (!ret) dis[u]=-1; return ret;
}
int dinic(int S,int T)
{
    int maxflow=0,tmp;
    while (bfs(S,T))
    {
        memcpy(cur,G,sizeof(G[0])*N);
        while (tmp=dfs(S,T,inf)) maxflow+=tmp;
    }
    return maxflow;
}
int x[600],y[600],z[600];
int n,m,X;
bool check(double ad)
{
    init(5000);
    for(int i=1;i<=m;i++)
        link(x[i],y[i],min(1.0*X,z[i]/(ad)));
    link(0,1,X);
    link(n,n+1,X);
    if(dinic(0,n+1)==X)return true;
    return false;
}
int main()
{

    scanf("%d%d%d",&n,&m,&X);
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&x[i],&y[i],&z[i]);
    double l=0,r=1e9,ans=0;
    for(int i=0;i<70;i++)
    {
        double mid = (l+r)/2.0;
        if(check(mid))l=mid,ans=mid;
        else r=mid;
    }
    printf("%.12f\n",ans*X);
}
    原文作者:qscqesze
    原文地址: https://www.cnblogs.com/qscqesze/p/5296536.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞