版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Swingss/article/details/82627719
题目链接:https://nanti.jisuanke.com/t/31447
这题是个可行流,网上搜了一堆题解发现都是贪心,然而我对拍了一下发现都有过不了的数据,我猜八成这题是不能用贪心解的,只能说题目数据太弱了。
加一个源点和一个汇点。建图。源点到左边点的容量为 [L, min(R, cnt[i])],(cnt[i] 为原图中点 i 的度数,[x, y] 表示该边流量的下界为 x,上界为 y);左边点到右边点容量为 [0, 1];右边点到汇点的容量为 [L, min(R, cnt[i])],含义与前面相同。然后跑一遍可行流就好了。
AC代码如下:
#include <algorithm>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-8;
// const double PI = acos(-1.0);
// const int MOD = 1000000007;
typedef long long LL;
typedef unsigned long long uLL;
const int N = 2000 * 2 + 10;
const int M = 2000000 + 10;
int n, m, k;
int L, R;
struct edge {
int a, b, cap;
};
vector<edge> es;
vector<int> g[N];
int s, t;
int x, y;
inline void addedge(int a, int b, int cap) {
if (cap == 0) return;
es.push_back({a, b, cap});
es.push_back({b, a, 0});
int i = es.size();
g[a].push_back(i - 2);
g[b].push_back(i - 1);
}
int d[N];
bool bfs() {
memset(d, -1, sizeof(d));
queue<int> q;
q.push(x);
d[x] = 0;
while (!q.empty()) {
int u = q.front();
q.pop();
for (auto i : g[u]) {
int v = es[i].b;
if (d[v] < 0 && es[i].cap > 0) {
d[v] = d[u] + 1;
q.push(v);
}
}
}
return d[y] >= 0;
}
bool vis[N];
int dfs(int u, int f) {
if (u == y) return f;
int ans = 0;
vis[u] = true;
for (auto i : g[u]) {
int v = es[i].b;
if (!vis[v] && d[v] == d[u] + 1 && es[i].cap > 0) {
int flow = dfs(v, min(f, es[i].cap));
if (flow > 0) {
es[i].cap -= flow;
es[i ^ 1].cap += flow;
ans += flow;
f -= flow;
if (f <= 0) break;
}
}
}
return ans;
}
int dinic() {
int ans = 0;
while (bfs()) {
int flow;
while (memset(vis, 0, sizeof(vis)), flow = dfs(x, INF)) ans += flow;
}
return ans;
}
bool solve() {
dinic();
bool ok = true;
for (auto i : g[x]) {
if (es[i].cap != 0) ok = false;
}
for (auto i : g[y]) {
if (es[i].cap != L) ok = false;
}
return ok;
}
int cnt[N];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
#ifdef LOCAL
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
int cs = 0;
while (cin >> n >> m >> k) {
cout << "Case " << ++cs << ": ";
cin >> L >> R;
t = n + m + 1;
x = t + 1;
y = t + 2;
for (int i = 0; i <= y; ++i) g[i].clear();
es.clear();
memset(cnt, 0, sizeof(cnt));
for (int i = 0; i < k; ++i) {
int u, v;
cin >> u >> v;
++cnt[u];
++cnt[v + n];
addedge(u, v + n, 1);
addedge(u, y, 0);
addedge(x, v, 0);
}
for (int i = 1; i <= n; ++i) {
if (cnt[i] < L) goto NO;
addedge(s, i, min(cnt[i], R) - L);
addedge(s, y, L);
addedge(x, i, L);
}
for (int i = n + 1; i < t; ++i) {
if (cnt[i] < L) goto NO;
addedge(i, t, min(cnt[i], R) - L);
addedge(i, y, L);
addedge(x, t, L);
}
addedge(t, s, INF);
if (solve()) {
cout << "Yes\n";
continue;
}
NO:
cout << "No\n";
}
return 0;
}