The Exchange of Items
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 (Xi, Yi), Bob can exchange one Xith item to one Yith 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 <= N, M <= 100).
The next N lines contains two integers: Ai and Bi (1 <= Ai, Bi <= 10,000).
Following M lines contains two integers: Xi and Yi (1 <= Xi, Yi <= 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
题意就是Bob有N个物品, 标号1~N, 接下来的N行为描述:第i件物品初始有Ai个,他最后想变成Bi个,他有M种交换物品的方法, 每一种描述为Xi,Yi, 表示他可以用一个Xi换一个Yi, 或者反过来…
最后问你如果可以交换成功的话,至少要交换多少次.
不难看出是个费用流…但是因为建图的时候挫了, 把每个物品拆成了两个点,然后忘记给i’ - j这样的连一条边..所以WA了下…
建图的话就是一个超级源连向N个点,流量为初始拥有值.然后N个点再连向N+1~2N的点上流量为INF,N~2*N的点再连到汇点上, 流量为目标值.以上边花费为0; 然后对于M种交换方式,每一种四条边, i->j’ , j->i’, i’->j, j’->i…流量为INF, 花费为1
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<iostream>
#define pb push_back
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
const int MAXN = 505;
const int MAXM = 50005;
const int INF = 0x3f3f3f3f;
struct Edge
{
int to,next,cap,flow,cost;
} edge[MAXM];
int head[MAXN],tol;
int pre[MAXN],dis[MAXN];
bool vis[MAXN];
int have[MAXN], want[MAXN];
int N;
void init(int n)
{
N = n;
tol = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u,int v,int cap,int cost)
{
edge[tol].to = v;
edge[tol].cap = cap;
edge[tol].cost = cost;
edge[tol].flow = 0;
edge[tol].next = head[u];
head[u] = tol++;
edge[tol].to = u;
edge[tol].cap = 0;
edge[tol].cost = -cost;
edge[tol].flow = 0;
edge[tol].next = head[v];
head[v] = tol++;
}
bool spfa(int s,int t)
{
queue<int>q;
for(int i = 0; i < N; i++)
{
dis[i] = INF;
vis[i] = false;
pre[i] = -1;
}
dis[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)
{
int v = edge[i].to;
if(edge[i].cap > edge[i].flow &&
dis[v] > dis[u] + edge[i].cost )
{
dis[v] = dis[u] + edge[i].cost;
pre[v] = i;
if(!vis[v])
{
vis[v] = true;
q.push(v);
}
}
}
}
if(pre[t] == -1)return false;
else return true;
}
int minCostMaxflow(int s,int t,int &cost)
{
int flow = 0;
cost = 0;
while(spfa(s,t))
{
//puts(" **test1** ");
int Min = INF;
for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
{
if(Min > edge[i].cap - edge[i].flow)
Min = edge[i].cap - edge[i].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;
}
return flow;
}
void solve()
{
int n, m;
while(~scanf("%d %d", &n, &m)){
init(2*n+2);
int sum = 0, haveSum = 0;
for(int i=1; i<=n; i++){
scanf("%d %d\n", &have[i], &want[i]);
sum += have[i];
haveSum += want[i];
addedge(0, i, have[i], 0);
addedge(i, i+n, INF, 0);
addedge(i+n, 2*n+1, want[i], 0);
}
for(int i=0; i<m; i++){
int u, v;
scanf("%d %d", &u, &v);
addedge(u, v+n, INF, 1);
addedge(v, u+n, INF, 1);
addedge(u+n, v, INF, 1);
addedge(v+n, u, INF, 1);
}
if(haveSum != sum){
puts("-1");
continue;
}
int ans = 0;
//puts("1");
int k = minCostMaxflow(0, 2*n+1, ans);
//printf("k : %d sum : %d ans : %d\n", k, sum, ans);
if(k == sum) printf("%d\n", ans);
else puts("-1");
//puts("2");
}
}
int main(void)
{
#ifdef DK
freopen("/home/dk/桌面/1.in","r",stdin);
#endif // DK
solve();
return 0;
}