zoj 3885 The Exchange of Items 【最小费用最大流】

The Exchange of Items


Time Limit: 2 Seconds      Memory Limit: 65536 KB



Bob lives in an ancient village, where transactions are done by one item exchange with another. Bob is very clever and he knows what items will become more valuable later on. So, Bob
has decided to do some business with villagers.

At first, Bob has N kinds of items indexed from 1 to N, and each item has Ai. There are M ways to exchanges items. For the ith
way (XiYi), Bob can exchange one Xith item to oneYith item, vice versa. Now Bob wants that his ith item has exactly Bi, and he wonders
what the minimal times of transactions is.

Input

There are multiple test cases.

For each test case: the first line contains two integers: N and M (1 <= NM <= 100).

The next N lines contains two integers: Ai and Bi (1 <= AiBi <= 10,000).

Following M lines contains two integers: Xi and Yi (1 <= XiYi <= N).

There is one empty line between test cases.

Output

For each test case output the minimal times of transactions. If Bob could not reach his goal, output -1 instead.

Sample Input

2 1
1 2
2 1
1 2

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

Sample Output

1
-1

Author: FENG, Jingyi

Source: ZOJ Monthly, July 2017

题意:Bob有N种物品,已知每种物品有Ai个,现在他想换成Bi个。给出有M种交换方式<Xi,Yi>(表示Xi物品和Yi物品可以互相转换)。问你——Bob达成目标所需要的最小交换次数,若不可能达成目标输出-1。

思路:最小费用最大流。记录目标状态的总流量sum,判断流入汇点的总流量是否等于sum。若等于说明目标状态可达,输出最小费用,反之不可达,输出-1。

建图:设置超级源点sink,超级汇点source。

1,sink向所有物品建边,容量为物品的初始数目,费用为0;

2,所有物品向source建边,容量为物品的目标数目,费用为0;

3,M种转换关系建双向边,容量为INF(为了能够达到目标状态,我们可以任意选择该边的流量),费用为1。

再跑一遍最小费用最大流,若最后的最大流flow等于目标状态的总流量则输出最小费用cost,反之输出-1。

AC代码:

#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
#define MAXN 110
#define MAXM 1000
#define INF 0x3f3f3f3f
using namespace std;
struct Edge
{
    int from, to, cap, flow, cost, next;
};
Edge edge[MAXM];
int head[MAXN], edgenum;
int pre[MAXN], dist[MAXN];
bool vis[MAXN];
int sink, source;//超级源点 超级汇点
int N, M;
int sum;//记录目标状态总流量
void init()
{
    edgenum = 0;
    memset(head, -1, sizeof(head));
}
void addEdge(int u, int v, int w, int c)
{
    Edge E1 = {u, v, w, 0, c, head[u]};
    edge[edgenum] = E1;
    head[u] = edgenum++;
    Edge E2 = {v, u, 0, 0, -c, head[v]};
    edge[edgenum] = E2;
    head[v] = edgenum++;
}
void getMap()
{
    int a, b;
    sum = 0;
    sink = 0, source = N+1;
    for(int i = 1; i <= N; i++)
    {
        scanf("%d%d", &a, &b);
        addEdge(sink, i, a, 0);//超级源点连i 容量为a 费用为0
        addEdge(i, source, b, 0);//i连超级汇点 容量为b 费用为0
        sum += b;//记录目标状态总流量
    }
    for(int i = 1; i <= M; i++)
        scanf("%d%d", &a, &b),
        addEdge(a, b, INF, 1), addEdge(b, a, INF, 1);//互建边 容量无穷大 费用1
}
bool SPFA(int s, int t)
{
    queue<int> Q;
    memset(dist, INF, sizeof(dist));
    memset(vis, false, sizeof(vis));
    memset(pre, -1, sizeof(pre));
    dist[s] = 0;
    vis[s] = true;
    Q.push(s);
    while(!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        vis[u] = false;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            Edge E = edge[i];
            if(dist[E.to] > dist[u] + E.cost && E.cap > E.flow)
            {
                dist[E.to] = dist[u] + E.cost;
                pre[E.to] = i;
                if(!vis[E.to])
                {
                    vis[E.to] = true;
                    Q.push(E.to);
                }
            }
        }
    }
    return pre[t] != -1;
}
void MCMF(int s, int t, int &cost, int &flow)
{
    cost = flow = 0;
    while(SPFA(s, t))
    {
        int Min = INF;
        for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
        {
            Edge E = edge[i];
            Min = min(Min, E.cap - E.flow);
        }
        for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
        {
            edge[i].flow += Min;
            edge[i^1].flow -= Min;
            cost += edge[i].cost * Min;
        }
        flow += Min;
    }
}
int main()
{
    while(scanf("%d%d", &N, &M) != EOF)
    {
        init();
        getMap();
        int cost, flow;
        MCMF(sink, source, cost, flow);
        if(flow == sum)//若流入汇点的总流量 等于 目标状态总流量 说明可行
            printf("%d\n", cost);
        else
            printf("-1\n");
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-11 07:48:37

zoj 3885 The Exchange of Items 【最小费用最大流】的相关文章

ZOJ 3885 The Exchange of Items(费用流)

ZOJ 3885 The Exchange of Items Description Bob lives in an ancient village, where transactions are done by one item exchange with another. Bob is very clever and he knows what items will become more valuable later on. So, Bob has decided to do some b

【BZOJ3876】【Ahoi2014】支线剧情 有下界的最小费用最大流

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43025375"); } [BZOJ2324]营救皮卡丘 这道题也是一道有下界的最小费用最大流. 我的题解地址:http://blog.csdn.net/vmurder/article/details/41378979 这道题其实就是模板题. 我的处理

POJ 3686.The Windy&#39;s 最小费用最大流

The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5477   Accepted: 2285 Description The Windy's is a world famous toy factory that owns M top-class workshop to make toys. This year the manager receives N orders for toys. The ma

P3381 【模板】最小费用最大流

P3381 [模板]最小费用最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行包含四个正整数ui.vi.wi.fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi. 输出格式: 一行,包含两个整数,依次为最大流量和在最大流量情况下的

C++之路进阶——最小费用最大流(支线剧情)

F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  hyxzc Logout 捐赠本站 Notice:由于本OJ建立在Linux平台下,而许多题的数据在Windows下制作,请注意输入.输出语句及数据类型及范围,避免无谓的RE出现. 3876: [Ahoi2014]支线剧情 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 542  Solved: 332[Submit

hdu 4494 Teamwork 最小费用最大流

Teamwork Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4494 Description Some locations in city A has been destroyed in the fierce battle. So the government decides to send some workers to repair these location

POJ - 2195 Going Home(最小费用最大流)

1.N*M的矩阵中,有k个人和k个房子,每个人分别进入一个房子中,求所有人移动的最小距离. 2.人看成源点,房子看成汇点,求最小费用最大流. 建图-- 人指向房子,容量为1,费用为人到房子的曼哈顿距离. 建立超级源点和超级汇点:超级源点指向人,容量为1,费用为0:超级汇点指向房子,容量为1,费用为0. 求超级源点到超级汇点的最小费用最大流即可. ps:容量为什么都设为1?---有待研究.. 3. 1.Bellman-Ford: #include<iostream> #include<st

hdu 1853 Cyclic Tour 最小费用最大流

题意:一个有向图,现在问将图中的每一个点都划分到一个环中的最少代价(边权和). 思路:拆点,建二分图,跑最小费用最大流即可.若最大流为n,则说明是最大匹配为n,所有点都参与,每个点的入度和出度又是1,所以就是环. /********************************************************* file name: hdu1853.cpp author : kereo create time: 2015年02月16日 星期一 17时38分51秒 *******

最小费用最大流

Farm Tour http://poj.org/problem?id=2135 建图再说吧 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<map> 6 #include<stack> 7 #include<queue> 8 #include<vector> 9 #include&l