TTTTTTTTTTTT CF 653D 送邮递员

链接:给一张n个点m条带权边的有向图,有x个人从起点出发到终点,每个人带的都带相同重量的货物, 
规定一条边最多能经过其上权的重量的货物,问最多能带多重的货物? 
2 ≤ n ≤ 50, 1 ≤ m ≤ 500, 1 ≤ x ≤ 100 000

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long Ull;
#define MM(a,b) memset(a,b,sizeof(a));
const double eps = 1e-10;
const ll inf = 1e16;
const double pi=acos(-1);
const int mod=100000000;

struct edge{
  int to;
  ll c;
  int rev;
};//注意顺序关系与(edge){}对应

vector<edge> G[55];
vector<edge> F[55];
int level[55],iter[55];
int n,m,x,u,v,c;


void bfs(int s)
{
     queue<int> q;
     q.push(s);
     level[s]=1;
     while(q.size())
     {
         int u=q.front();q.pop();
         for(int i=0;i<G[u].size();i++)
         {
             edge e=G[u][i];
             if(e.c>0&&level[e.to]==-1)
             {
                 level[e.to]=level[u]+1;
                 q.push(e.to);
             }
         }
     }
}

double dfs(int s,int t,double minn)
{
     if(s==t) return minn;
     for(int &i=iter[s];i<G[s].size();i++)
     {
         edge &e=G[s][i];
         if(e.c>0&&level[e.to]>level[s])
         {
            int d=dfs(e.to,t,min((double)minn,(double)e.c));
            if(d>0)
            {
                e.c-=d;
                G[e.to][e.rev].c+=d;
                 return d;
             }
         }
     }
     return 0;
}

bool ok(double mid)
{
    for(int i=1;i<=n;i++) G[i].clear();
    for(int i=1;i<=n;i++)
        for(int j=0;j<F[i].size();j++)
        {
            G[i].push_back(F[i][j]);
            G[i][j].c=(ll)(F[i][j].c/mid);//精度很重要
        }
    double ans=0,temp;
    for(;;)
    {
        MM(level,-1);
        bfs(1);
        if(level[n]<0) break;
        MM(iter,0);
        while((temp=dfs(1,n,inf))>0)
            ans+=temp;
    }
    return ans>=x;
}

int main()
{
    double l,r;
    while(~scanf("%d %d %d",&n,&m,&x))
    {
           for(int i=1;i<=n;i++)  F[i].clear();
           l=0;r=0;
           for(int i=1;i<=m;i++)
                 {
                     scanf("%d %d %d",&u,&v,&c);
                     F[u].push_back((edge){v,c,F[v].size()});
                     F[v].push_back((edge){u,0,F[u].size()-1});
                     r=max(r,(double)c);//库里的max参数
                 }
           for(int i=1;i<=200;i++)
           {
               double mid=(l+r)/2;
               if(ok(mid)) l=mid;
               else r=mid;
           }
           printf("%.10f
",r*x);
    }
    return 0;
}

 分析:这道题精度卡的很恶心,但是用double的话这道题就没什么问题了;

参考资料 深刻的领会了long long的强大,,double的有效位数是15-17位,但是能表示的范围

可以达到10^308,,因为是科学计数法,,,double是 1.1234567890123456E指数这种表示的

原文地址:https://www.cnblogs.com/smilesundream/p/5397251.html