問題:コストフロー(ネットワークフロー)

タイトル

ポータル

思考

この質問は、コストの流れの対象であります

コストの流れで行うにはしかし、実際には何もありません、

私たちはまず、ボブの最適な戦略を考えます

ボブそれを

\(ANS = \ sum_ {i = 1} ^ {M} w_i * flow_i \)

私たちは、ボブのためにそれを発見しました

最適な戦略は、1辺の最大の流れの中で、すべての憎悪にすべてのユニットを過ごすためにでなければなりません

ボブは、後に最適な戦略を知っています

アリスのために、トラフィックフローを可能な限り小さく最大の片側で、

確実に最大値は変わらず流れている間

明らかに、このよう単調があります

だから我々は半分を考慮することができます

各エッジの最大容量を制限するために使用される二つの中間点

最大流量は、ライン上で確認することピ​​ットインした後

コード

#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
using namespace std;
const double eps=1e-9;
struct node
{
    int u,v;
    double w;
};
int n,m;
double p;
double l,r,mid;
double max_f;
vector<node>v;
struct networt_flow_isap
{
    #define MAXN 205
    double c[MAXN][MAXN];
    int d[MAXN];
    int vd[MAXN];
    double maxx;
    int s,t;
    vector<int> g[MAXN];
    #undef MAXN
    void add(int u,int v,double w)
    {
        g[u].push_back(v);
        g[v].push_back(u);
    }
    void init()
    {
        maxx=0;
        memset(c,0,sizeof(c));  
        memset(d,0,sizeof(d));
        memset(vd,0,sizeof(vd));
        for(int i=1;i<=n;i++)
            g[i].clear();

    }
    double dfs(int u,double f)
    {
        if(u==t)
            return f;
        double minn=0,summ=0;
        int id=n-1;
        for(int i=0;i<g[u].size();i++)
        {
            int v=g[u][i];
            if(c[u][v]>0)
            {
                if(d[u]==d[v]+1)
                {
                    minn=min(f-summ,c[u][v]);
                    minn=dfs(v,minn);
                    c[u][v]-=minn;
                    c[v][u]+=minn;
                    summ+=minn;
                    if(d[s]>=n)
                        return summ;
                    if(summ==f)
                        break;
                }
                if(d[v]<id)
                    id=d[v];
            }
        }
        if(summ==0)
        {
            vd[d[u]]--;
            if(!vd[d[u]])
                d[s]=n;
            d[u]=id+1;
            vd[d[u]]++;
        }
            
        return summ;
    }
    double isap(int S,int T)
    {
        memset(d,0,sizeof(d));
        memset(vd,0,sizeof(vd));
        s=S;
        t=T;
        vd[0]=n;
        maxx=0;
        while(d[s]<n)
            maxx+=dfs(s,(1ll<<60)/2);
        return maxx;
    }
}g;
void init(double cnt)
{
    memset(g.c,0,sizeof(g.c));
    for(int i=0;i<v.size();i++)
    {
        g.c[v[i].u][v[i].v]+=min(v[i].w,cnt);
        g.c[v[i].v][v[i].u]=0;
    }
}
double f_abs(double x)
{
    if(x<0)
        return -x;
    return x;
}
bool check(double cnt)
{
    init(cnt);
    double ans=g.isap(1,n);
    //cout<<cnt<<' '<<ans<<'\n';
    if(f_abs(ans-max_f)<eps)
        return 1;
    return 0;
}
int main()
{
    cin>>n>>m>>p;
    for(int i=1;i<=m;i++)
    {
        int x,y;
        double z;
        cin>>x>>y>>z;
        v.push_back((node){x,y,z});
        g.add(x,y,z);
    }
    init(1e9);
    max_f=g.isap(1,n);
    cout<<max_f<<'\n';
    l=0;
    r=1e9;
    while(l+eps<r)
    {
        mid=(l+r)/2;
        if(check(mid))
            r=mid;
        else
            l=mid;
    }
    printf("%.5lf",mid*p);
    return 0;
}

おすすめ

転載: www.cnblogs.com/loney-s/p/12031008.html