51nod 1442 士兵的旅行(最大流)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1442

在某个国家有n个城市,他们通过m条无向的道路相连。每个城市有一支军队。第i个城市的军队有ai个士兵。现在士兵开始移动。每个士兵可以呆在原地,或者走到和他所在城市直接相邻的城市,即设每一条边长度为1的话,他离开之后不能距离原来城市大于1。

判断移动之后,能不能使得第i个城市恰好有bi个士兵。

Input

单组测试数据。
第一行有两个整数n和m(1 ≤ n ≤ 100, 0 ≤ m ≤ 200)。
第二行包含n个整数 a1, a2, ..., an (0 ≤ ai ≤ 100)。
第三行包含n个整数b1, b2, ..., bn (0 ≤ bi ≤ 100)。
接下来m行,每行给出两个整数 p 和q (1 ≤ p, q ≤ n, p ≠ q),表示p和q之间有一条无向的道路。
每两个城市之间最多有一条无向的道路。

Output

如果能够调整成功,输出YES,否则输出NO。

Input示例

4 4
1 2 6 3
3 5 3 1
1 2
2 3
3 4
4 2

Output示例

YES

最大流求解,源点连城市流量ai,城市连汇点流量bi,下面的边是无向图,拆点后建有向的就可以了,最后判断满流

#include <queue>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 1010;
struct edge {
	int to, cap, rev;
	edge(int a, int b, int c) { to = a; cap = b; rev = c; }
};
vector<edge>g[maxn];
int level[maxn], iter[maxn];
void addedge(int from,int to,int cap)
{
	g[from].push_back(edge( to,cap,g[to].size() ));
	g[to].push_back(edge( from,0,g[from].size() - 1 ));
}
void bfs(int s)
{
	memset(level, -1, sizeof(level));
	queue<int>que;
	level[s] = 0;
	que.push(s);
	while (!que.empty())
	{
		int u = que.front();
		que.pop();
		for (int i = 0; i < g[u].size(); i++)
		{
			edge &e = g[u][i];
			if (e.cap > 0 && level[e.to] < 0)
			{
				level[e.to] = level[u] + 1;
				que.push(e.to);
			}
		}
	}
}
int dfs(int v, int t, int f)
{
	if (v == t)
	{
		return f;
	}
	for (int &i = iter[v]; i < g[v].size(); i++)
	{
		edge &e = g[v][i];
		if (e.cap > 0 && level[v] < level[e.to])
		{
			int d = dfs(e.to, t, min(f, e.cap));
			if (d > 0)
			{
				e.cap -= d;
				g[e.to][e.rev].cap += d;
				return d;
			}
		}
	}
	return 0;
}
int maxflow(int s, int t)
{
	int flow = 0;
	while (1)
	{
		bfs(s);
		if (level[t] < 0)
		{
			return flow;
		}
		memset(iter, 0, sizeof(iter));
		int f;
		while ((f = dfs(s, t, inf) )> 0)
		{
			flow += f;
		}
	}
}
int main() 
{
	//freopen("C://input.txt", "r", stdin);
	int n, m;
	scanf("%d%d", &n, &m);
	int sum1, sum2;
	sum1 = sum2 = 0;
	int a, b;
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &a);
		addedge(i, i + n, inf);
		addedge(0, i, a);
		sum1 += a;
	}
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &b);
		addedge(i + n, 2 * n + 1, b);
		sum2 += b;
	}
	for (int i = 0; i < m; i++)
	{
		scanf("%d%d", &a, &b);
		addedge(a, b + n, inf);
		addedge(b, a + n, inf);
	}
	int ans = maxflow(0, 2 * n + 1);
	if (ans == sum2 && sum2 == sum1)
	{
		printf("YES\n");
	}
	else
	{
		printf("NO\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Evildoer_llc/article/details/83247052