牛客多校第一场 带花树模板 I - 1 or 2
题意
- 给定一个有
n
n
n个节点,
m
m
m条边的图,给定一个数组
d
d
d,
d
[
i
]
d[i]
d[i]表示第i个节点恰好有
d
[
i
]
d[i]
d[i]个匹配
数据范围:
1
≤
n
≤
60
,
1
≤
m
≤
100
,
1
≤
d
[
i
]
≤
2
1\leq n \leq 60, 1 \leq m \leq 100 , 1 \leq d[i] \leq 2
1≤n≤60,1≤m≤100,1≤d[i]≤2
前置技能
Tutorial:
复杂度:
O
(
n
3
)
O(n^3)
O(n3)
code:
#include <bits/stdc++.h>
using namespace std;
#define _rep(n, a, b) for (ll n = (a); n <= (b); ++n)
#define _rev(n, a, b) for (ll n = (a); n >= (b); --n)
#define _for(n, a, b) for (ll n = (a); n < (b); ++n)
#define _rof(n, a, b) for (ll n = (a); n > (b); --n)
#define oo 0x3f3f3f3f3f3f
#define ll long long
#define db long double
#define eps 1e-3
#define bin(x) cout << bitset<10>(x) << endl;
#define what_is(x) cerr << #x << " is " << x << endl
#define met(a, b) memset(a, b, sizeof(a))
#define all(x) x.begin(), x.end()
#define pii pair<ll, ll>
#define pdd pair<db, db>
#define endl "\n"
const ll mod = 998244353;
const ll maxn = 2e3 + 10;
vector<int> G[maxn];
ll qpow(ll a, ll b) {
ll ret = 1;
for (; b; a = a * a % mod, b >>= 1) {
if (b & 1) {
ret = ret * a % mod;
}
}
return ret;
}
vector<ll> f(maxn), invf(maxn);
ll inv(ll a) {
return qpow(a, mod - 2);
}
void prework() {
f[0] = 1;
_rep(i, 1, maxn - 1) {
f[i] = f[i - 1] * i % mod;
}
invf[maxn - 1] = qpow(f[maxn - 1], mod - 2);
for (int i = maxn - 2; i >= 0; i--) {
invf[i] = invf[i + 1] * (i + 1) % mod;
}
}
ll C(ll n, ll m) {
if (n > m || m < 0)return 0;
if (n == 0 || m == n) return 1;
ll res = (f[m] * invf[m - n] % mod * invf[n]) % mod;
return res;
}
int n, m;
deque<int> Q;
bool g[maxn][maxn], inque[maxn], inblossom[maxn], inpath[maxn];
int match[maxn], pre[maxn], base[maxn];
int findancestor(int u, int v) {
for (int i = 1; i <= n; i++)inpath[i] = 0;
while (1) {
u = base[u];
inpath[u] = true;
if (match[u] == -1)break;
u = pre[match[u]];
}
while (1) {
v = base[v];
if (inpath[v])return v;
v = pre[match[v]];
}
}
void reset(int u, int anc) {
while (u != anc) {
int v = match[u];
inblossom[base[u]] = 1;
inblossom[base[v]] = 1;
v = pre[v];
if (base[v] != anc)pre[v] = match[u];
u = v;
}
}
void contract(int u, int v, int n) {
int anc = findancestor(u, v);
for (int i = 1; i <= n; i++)inblossom[i] = 0;
reset(u, anc);
reset(v, anc);
if (base[u] != anc)pre[u] = v;
if (base[v] != anc)pre[v] = u;
for (int i = 1; i <= n; i++)
if (inblossom[base[i]]) {
base[i] = anc;
if (!inque[i]) {
Q.push_back(i);
inque[i] = 1;
}
}
}
bool bfs(int S, int n) {
for (int i = 0; i <= n; i++)pre[i] = -1, inque[i] = 0, base[i] = i;
Q.clear();
Q.push_back(S);
inque[S] = 1;
while (!Q.empty()) {
int u = Q.front();
Q.pop_front();
for (int v = 1; v <= n; v++) {
if (g[u][v] && base[v] != base[u] && match[u] != v) {
if (v == S || (match[v] != -1 && pre[match[v]] != -1))contract(u, v, n);
else if (pre[v] == -1) {
pre[v] = u;
if (match[v] != -1)Q.push_back(match[v]), inque[match[v]] = 1;
else {
u = v;
while (u != -1) {
v = pre[u];
int w = match[v];
match[u] = v;
match[v] = u;
u = w;
}
return true;
}
}
}
}
}
return false;
}
bool solve() {
for (int i = 1; i <= n; i++)match[i] = -1;
int ans = 0;
for (int i = 1; i <= n; i++) {
if (match[i] == -1 && bfs(i, n)) ans++;
}
return ans == n / 2;
}
int d[maxn], d1[maxn], l[maxn], r[maxn];
int u[maxn], v[maxn];
bool build() {
memset(g, 0, sizeof g);
memset(l, 0, sizeof l);
int cnt = 0;
for (int i = 1; i <= n; i++)
if (d1[i] > d[i]) return 0;
for (int i = 1; i <= m; i++) {
if (!l[u[i]]) {
l[u[i]] = ++cnt;
r[u[i]] = d[u[i]] - d1[u[i]] + cnt - 1;
cnt += d[u[i]] - d1[u[i]] - 1;
}
if (!l[v[i]]) {
l[v[i]] = ++cnt;
r[v[i]] = d[v[i]] - d1[v[i]] + cnt - 1;
cnt += d[v[i]] - d1[v[i]] - 1;
}
int k = cnt + 2;
cnt += 2;
g[k][k - 1] = g[k - 1][k] = 1;
for (int j = l[u[i]]; j <= r[u[i]]; j++)
g[j][k] = g[k][j] = 1;
for (int j = l[v[i]]; j <= r[v[i]]; j++)
g[k - 1][j] = g[j][k - 1] = 1;
}
n = cnt;
return 1;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
while (cin >> n >> m) {
met(d, 0);
_rep(i, 1, n) {
cin >> d1[i];
}
_rep(i, 1, m) {
cin >> u[i] >> v[i];
d[u[i]]++;
d[v[i]]++;
}
if (build() && solve())
cout << "Yes" << endl;
else cout << "No" << endl;
}
}