P3381 [テンプレート]最小コスト最大値(MCMF)

P3381 [テンプレート]最小コストの最大

ネットワーク図与えられた主題の説明、およびソースとシンクと、各側部ユニットは、最大流量の場合には最大流量と最小コストネットワークを決定する最大流量とトラフィック電荷を、知られています。

入力フォーマットは、最初の行は、4つの正の整数N、M、S、Tを含み、それぞれ、エッジの数、ソースポイント番号、シリアル番号シンクとの点の数。

次のMラインは4つの整数UI、VI、WIが含ま、Fiは、そこから端までのI番目のUIを示し、単位流量当たり、VI、WIの右側(最大流量のWiの、すなわち、側)に到着します手数料Fiを提供しています。

フォーマット出力最大流量条件で最大流量と最小コストに続く2つの整数を含む一行。

サンプル入力と出力

输入 #1 复制

4 5 4 3
4 2 30 2
4 3 20 3
2 3 20 1
2 1 30 9
1 3 40 5
输出 #1 复制

50 280

時間の説明/ヒント制約:1000ミリ秒、128M

(BYX:1200msに最後の二点)

データスケール:

N <= 10、M <= 10:データの30%を

N <= 1000、M <= 1000:データの70%を

データの100%まで:N <= 5000、M <= 50000

サンプルの説明:

ここに画像を挿入説明

示されるように、以下のように、最適解は次のとおりです。

第一の流れは20の4-> 3、流量、3×20 = 60のコストです。

第二の流れは、4-> 2-> 3、20の流量は、コストは(2 + 1)* 20 = 60です。

第三の流れは、図10に示すように、コスト(9 + 2 + 5)×10 = 160の4> 2-> 1-> 3、流量です。

したがって、最大流量は、この場合の最小コストは60 + 60 + 160 = 280であり、50です。

したがって、50280の出力。

思考

Spfa + Dinic

問題を解決するため、以下のように

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

#define INF 0x3f3f3f3f
#define ll long long
const int maxn = 5005;
const int maxm = 150000;
int n, m, s, e;
struct Edge
{
    int v, w, cap, next;
} edge[maxm];
int head[maxn], dis[maxn], use[maxn];
int pre[maxn], last[maxm];      //pre 是用来存储上一个节点的, 而last 则是存储上一个边
int flow[maxn];
int k = -1;
ll mx_flw = 0, mn_cst = 0;

void Add(int u, int v, int w, int cap)
{
    edge[++ k] = (Edge){ v, w, cap, head[u]}; head[u] = k;
    edge[++ k] = (Edge){ u, -w, 0, head[v]};  head[v] = k;
}

bool Spfa(int s, int e)
{
    int ar[10];
    for(int i = 0; i <= n; i ++)
        dis[i] = INF, use[i] = 0, flow[i] = INF;
    dis[s] = 0;
    queue<int> q;
    q.push(s);
    int u,v,w;
    while(! q.empty())
    {
        u = q.front(); q.pop();
        use[u] = 0;

        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            v = edge[i].v;
            w = edge[i].w;
            if(edge[i].cap && dis[v] > dis[u] + w)
            {
                dis[v] = dis[u] + w;
                pre[v] = u;
                last[v] = i;
                flow[v] = min(flow[u], edge[i].cap);
                if(! use[v])
                {
                    q.push(v);
                    use[v] = 1;
                }
            }
        }
    }
    if(flow[e] != INF)
        return true;
    return false;
}

void MCMF(int s, int e)
{
    while(Spfa(s, e))
    {
        mx_flw += flow[e];
        mn_cst += flow[e]*1LL * dis[e]*1LL;
        int now = e;
        while(now != s)     //更新 残量
        {
            edge[last[now]].cap -= flow[e];
            edge[last[now]^1].cap += flow[e];
            now = pre[now];
        }
    }
}

void init()
{
    k = -1;
    for(int i = 0; i <= n; i ++)
        head[i] = -1;
    mx_flw = 0, mn_cst = 0;
}

int main()
{
    ios::sync_with_stdio(false); cin.tie(0);
    //freopen("T.txt","r",stdin);
    while(cin >> n >> m >> s >> e)
    {
        init();
        int u, v, cap, w;
        for(int i = 1; i <= m; i ++)
            cin >> u >> v >> cap >> w, Add(u, v, w, cap);
        MCMF(s, e);
        cout << mx_flw << " " << mn_cst << endl;
    }

    return 0;
}
公開された122元の記事 ウォンの賞賛191 ・は 20000 +を見て

おすすめ

転載: blog.csdn.net/qq_34261446/article/details/104563650