#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; #define int long long #define st first #define nd second #define pb push_back #define mp make_pair #define rep(i,a,b) for(ll i=(ll)a;i<=(ll)b;++i) #define all(a) a.begin(),a.end() #define sz(x) (int)(x).size() const int mxN = 2e5+7, mod = 1e9+7; vector<int> graf[mxN]; bool a[mxN]; int c[mxN]; int cnt[2][2]; bool dfs(int v,int pop){ c[v] = pop; cnt[pop][a[v]]++; bool res = 1; for(auto u : graf[v]){ if(c[v] == c[u]) res = 0; if(c[u] == -1) res &= dfs(u, pop^1); } return res; } template<typename T> struct Newton{ int n; vector<T> frac, rfrac; Newton(int n_) : n(n_), frac(n_+1), rfrac(n_+1) {} T InverseMod(T a, T w = mod-2){ T res = 1; while(w){ if(w&1) res = (res * a)%mod; a = (a*a)%mod; w /= 2; } return res; } void prep(){ frac[0] = 1; for(int i=1;i<=n;i++) frac[i] = (frac[i-1]*i) % mod; rfrac[n] = InverseMod(frac[n]); for(int i=n-1;i>=0;i--) rfrac[i] = (rfrac[i+1]*(i+1)) % mod; } T choose(T a, T b){ if(b > a) return 0; return (((frac[a]*rfrac[b])%mod)*rfrac[a-b])%mod; } }; int32_t main(){ ios_base::sync_with_stdio(0); cin.tie(0); int n,m; cin >> n >> m; rep(i,1,n) cin >> a[i]; while(m--){ int u,v; cin >> u >> v; graf[u].pb(v); graf[v].pb(u); } rep(i,1,n) c[i] = -1; int res = 1; Newton<int> C(n+7); C.prep(); rep(i,1,n) if(c[i] == -1){ rep(x,0,1) rep(y,0,1) cnt[x][y] = 0; bool b = dfs(i, 0); if(b){ int akt = 0; while(cnt[0][0] >= 1 && cnt[1][0] >= 1){ cnt[0][0]--; cnt[0][1]++; cnt[1][0]--; cnt[1][1]++; } while(cnt[0][1] >= 0 && cnt[1][1] >= 0){ akt = (akt+(C.choose(cnt[0][0]+cnt[0][1], cnt[0][0])*C.choose(cnt[1][0]+cnt[1][1], cnt[1][0]))%mod)%mod; cnt[0][0]++; cnt[0][1]--; cnt[1][0]++; cnt[1][1]--; } res = (res*akt)%mod; }else{ int akt = 0; rep(x,0,1) cnt[0][x] += cnt[1][x]; while(cnt[0][0] >= 2){ cnt[0][0] -= 2; cnt[0][1] += 2; } while(cnt[0][1] >= 0){ akt = (akt+C.choose(cnt[0][0]+cnt[0][1], cnt[0][0]))%mod; cnt[0][0] += 2; cnt[0][1] -= 2; } res = (res*akt)%mod; } } cout << res << "\n"; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; #define int long long #define st first #define nd second #define pb push_back #define mp make_pair #define rep(i,a,b) for(ll i=(ll)a;i<=(ll)b;++i) #define all(a) a.begin(),a.end() #define sz(x) (int)(x).size() const int mxN = 2e5+7, mod = 1e9+7; vector<int> graf[mxN]; bool a[mxN]; int c[mxN]; int cnt[2][2]; bool dfs(int v,int pop){ c[v] = pop; cnt[pop][a[v]]++; bool res = 1; for(auto u : graf[v]){ if(c[v] == c[u]) res = 0; if(c[u] == -1) res &= dfs(u, pop^1); } return res; } template<typename T> struct Newton{ int n; vector<T> frac, rfrac; Newton(int n_) : n(n_), frac(n_+1), rfrac(n_+1) {} T InverseMod(T a, T w = mod-2){ T res = 1; while(w){ if(w&1) res = (res * a)%mod; a = (a*a)%mod; w /= 2; } return res; } void prep(){ frac[0] = 1; for(int i=1;i<=n;i++) frac[i] = (frac[i-1]*i) % mod; rfrac[n] = InverseMod(frac[n]); for(int i=n-1;i>=0;i--) rfrac[i] = (rfrac[i+1]*(i+1)) % mod; } T choose(T a, T b){ if(b > a) return 0; return (((frac[a]*rfrac[b])%mod)*rfrac[a-b])%mod; } }; int32_t main(){ ios_base::sync_with_stdio(0); cin.tie(0); int n,m; cin >> n >> m; rep(i,1,n) cin >> a[i]; while(m--){ int u,v; cin >> u >> v; graf[u].pb(v); graf[v].pb(u); } rep(i,1,n) c[i] = -1; int res = 1; Newton<int> C(n+7); C.prep(); rep(i,1,n) if(c[i] == -1){ rep(x,0,1) rep(y,0,1) cnt[x][y] = 0; bool b = dfs(i, 0); if(b){ int akt = 0; while(cnt[0][0] >= 1 && cnt[1][0] >= 1){ cnt[0][0]--; cnt[0][1]++; cnt[1][0]--; cnt[1][1]++; } while(cnt[0][1] >= 0 && cnt[1][1] >= 0){ akt = (akt+(C.choose(cnt[0][0]+cnt[0][1], cnt[0][0])*C.choose(cnt[1][0]+cnt[1][1], cnt[1][0]))%mod)%mod; cnt[0][0]++; cnt[0][1]--; cnt[1][0]++; cnt[1][1]--; } res = (res*akt)%mod; }else{ int akt = 0; rep(x,0,1) cnt[0][x] += cnt[1][x]; while(cnt[0][0] >= 2){ cnt[0][0] -= 2; cnt[0][1] += 2; } while(cnt[0][1] >= 0){ akt = (akt+C.choose(cnt[0][0]+cnt[0][1], cnt[0][0]))%mod; cnt[0][0] += 2; cnt[0][1] -= 2; } res = (res*akt)%mod; } } cout << res << "\n"; } |