链接:https://ac.nowcoder.com/acm/contest/5666/I
来源:牛客网
题目描述
Bobo has a graph with n n n vertices and m m m edges where the i i i-th edge is between the vertices a i a_i ai and b i b_i bi. Find out whether is possible for him to choose some of the edges such that the i i i-th vertex is incident with exactly d i d_i di edges.
输入描述:
The input consists of several test cases terminated by end-of-file.
The first line of each test case contains two integers n n n and m m m.
The second line contains n n n integers d 1 , d 2 , … , d n d_1, d_2, \dots, d_n d1,d2,…,dn.
The i i i-th of the following m m m lines contains two integers a i a_i ai and b i b_i bi.
输出描述:
For each test case, print “Yes
” without quotes if it is possible. Otherwise, print “No
” without quotes.
示例1
输入
2 1
1 1
1 2
2 1
2 2
1 2
3 2
1 1 2
1 3
2 3
输出
Yes
No
Yes
对于某条边 e x , y e_{x,y} ex,y,将边拆成两个点 e 1 e_1 e1, e 2 e_2 e2,在 e 1 e_1 e1, e 2 e_2 e2之间连边,在 x x x, e 1 e_1 e1之间连边, e 2 e_2 e2, y y y之间连边。如果 d [ x ] = 2 d[x]=2 d[x]=2,将 x x x拆出一个点 x ′ x' x′,在 x ′ x' x′, e 1 e_1 e1之间连边,点 y y y同理。
样例3
3 2
1 1 2
1 3
2 3
建图如下。
对所建图求一般图最大匹配,如果存在完美匹配则输出"Yes",否则输出"No"。
#include
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scahf("%c",&a);
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define ull unsigned long long
#define vi vector
#define pii pair
#define mii unordered_map
#define msi unordered_map
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define pr(x) cout<<#x<<": "<
using namespace std;
inline int qr() {
int f = 0, fu = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-')fu = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
f = (f << 3) + (f << 1) + c - 48;
c = getchar();
}
return f * fu;
}
const int N = 305;
struct BA {
int n;
bool G[N][N];
int Match[N];
bool InQueue[N], InPath[N], InBlossom[N];
int Head, Tail;
int Queue[N];
int Start, Finish;
int NewBase;
int Father[N], Base[N];
int Count;
inline void add(int x, int y) {
G[x][y] = G[y][x] = true;
}
inline void init(int _n) {
n = _n, ms(G);
}
inline void Push(int u) {
Queue[Tail] = u;
Tail++;
InQueue[u] = true;
}
inline int Pop() {
int res = Queue[Head];
Head++;
return res;
}
inline int FindCommonAncestor(int u, int v) {
ms(InPath);
while (true) {
u = Base[u];
InPath[u] = true;
if (u == Start) break;
u = Father[Match[u]];
}
while (true) {
v = Base[v];
if (InPath[v])break;
v = Father[Match[v]];
}
return v;
}
inline void ResetTrace(int u) {
int v;
while (Base[u] != NewBase) {
v = Match[u];
InBlossom[Base[u]] = InBlossom[Base[v]] = true;
u = Father[v];
if (Base[u] != NewBase) Father[u] = v;
}
}
inline void BloosomContract(int u, int v) {
NewBase = FindCommonAncestor(u, v);
ms(InBlossom);
ResetTrace(u);
ResetTrace(v);
if (Base[u] != NewBase) Father[u] = v;
if (Base[v] != NewBase) Father[v] = u;
repi(tu, 1, n)if (InBlossom[Base[tu]]) {
Base[tu] = NewBase;
if (!InQueue[tu]) Push(tu);
}
}
inline void FindAugmentingPath() {
ms(InQueue), ms(Father);
repi(i, 1, n) Base[i] = i;
Head = Tail = 1;
Push(Start);
Finish = 0;
while (Head < Tail) {
int u = Pop();
repi(v, 1, n)if (G[u][v] && (Base[u] != Base[v]) && (Match[u] != v)) {
if ((v == Start) || ((Match[v] > 0) && Father[Match[v]] > 0))
BloosomContract(u, v);
else if (Father[v] == 0) {
Father[v] = u;
if (Match[v] > 0)
Push(Match[v]);
else {
Finish = v;
return;
}
}
}
}
}
inline void AugmentPath() {
int u, v, w;
u = Finish;
while (u > 0) {
v = Father[u];
w = Match[v];
Match[v] = u;
Match[u] = v;
u = w;
}
}
inline void Edmonds() {
ms(Match);
repi(u, 1, n)if (Match[u] == 0) {
Start = u;
FindAugmentingPath();
if (Finish > 0) AugmentPath();
}
}
inline void PrintMatch() {
Count = 0;
repi(u, 1, n) if (Match[u] > 0) Count++;
printf("%d\n", Count);
repi(u, 1, n) if (u < Match[u])
printf("%d %d\n", u, Match[u]);
}
} B;
int n, m;
int d[55];
int main() {
while (scanf("%d%d", &n, &m) != EOF) {
B.init(n * 2 + m * 2);
int tot = n * 2, num = m * 2;
repi(i, 1, n)d[i] = qr(), num += d[i];
repi(i, 1, m) {
int x = qr(), y = qr();
B.add(tot + 1, tot + 2);
B.add(x, tot + 1), B.add(tot + 2, y);
if (d[x] == 2)B.add(x + n, tot + 1);
if (d[y] == 2)B.add(tot + 2, y + n);
tot += 2;
}
B.Edmonds();
int cnt = 0;
repi(i, 1, n * 2 + m * 2)if (B.Match[i])cnt++;
puts(cnt == num ? "Yes" : "No");
}
return 0;
}