1 or 2

链接: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.

  • 1 ≤ n ≤ 50 1 \leq n \leq 50 1n50
  • 1 ≤ m ≤ 100 1 \leq m \leq 100 1m100
  • 1 ≤ d i ≤ 2 1 \leq d_i \leq 2 1di2
  • 1 ≤ a i , b i ≤ n 1 \leq a_i, b_i \leq n 1ai,bin
  • a i ≠ b i a_i \neq b_i ai=bi
  • { a i , b i } ≠ { a j , b j } \{a_i, b_i\} \neq \{a_j, b_j\} {ai,bi}={aj,bj} for i ≠ j i \neq j i=j
  • The number of tests does not exceed 100 100 100.

输出描述:
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

建图如下。
1 or 2_第1张图片
对所建图求一般图最大匹配,如果存在完美匹配则输出"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;
}

你可能感兴趣的:(一般图最大匹配,ACM)