#include<iostream> #include<algorithm> #include<vector> #include<cmath> #include<ctime> #include<cstring> #include<limits> #include<complex> using namespace std; const long long m = 1000000007; const int c = 200000; long long factorial[c+1]; long long inv(long long a) { return a <= 1 ? a : m - (long long)(m/a) * inv(m % a) % m; } long long bin(int n, int k) { return factorial[n] * inv(factorial[k] * factorial[n - k] % m) % m; } long long pot(int n) { long long ans = 1; for(int i=0; i<n; ++i) ans = (ans * 2) % m; return ans; } struct FAU { int *p, *w; FAU(int n) : p(new int[n]), w(new int[n]) { for(int x=0; x<n; ++x) p[x] = w[x] = -1; } ~FAU() { delete[]p; delete[]w; } int Find(int x) { return (p[x] < 0) ? x : p[x] = Find(p[x]); } void Union(int x, int y) { if((x = Find(x)) == (y = Find(y))) return; if(w[x] > w[y]) p[y] = x; else p[x] = y; if(w[x] == w[y]) w[y]++; } }; int main() { ios::sync_with_stdio(0); factorial[0] = 1; for (int i = 1; i <= c; i++) { factorial[i] = factorial[i - 1] * i % m; } int N,M; cin>>N>>M; int Z[c+1],a[c*2],b[c*2]; for(int i=1; i<=N; ++i) cin>>Z[i]; vector<int> L[c+1]; for(int i=0; i<M; ++i) { cin>>a[i]>>b[i]; L[a[i]].push_back(b[i]); L[b[i]].push_back(a[i]); } FAU fau(N+1); for(int i=1; i<=N; ++i) { int r = L[i].size(); for(int j=1; j<r; ++j) fau.Union(L[i][0], L[i][j]); } int nr[c+1]; int il[c+1]; int jed[c+1]; for(int i=0; i<=N; ++i) nr[i] = il[i] = jed[i] = 0; for(int i=1; i<=N; ++i) { int pom = fau.Find(i); nr[pom] = 1; il[pom]++; if(Z[i] == 1) jed[pom]++; } for(int i=0; i<M; ++i) { if(fau.Find(a[i]) == fau.Find(b[i])) { nr[fau.Find(a[i])] = 2; } } long long ans = 1; for(int i=0; i<M; ++i) { int e,f; e = fau.Find(a[i]); f = fau.Find(b[i]); if(e != f && nr[e]*nr[f] != 0) { if(nr[e] == 2 || nr[f] == 2) { ans = (ans * pot(il[e]+il[f]-1)) % m; } else { if(jed[e] > jed[f]) { int h = jed[e] - jed[f]; long long H = 0; for(int i=0; i<=min(il[f], il[e] - h); ++i) { H += (bin(il[f], i) * bin(il[e], i + h)) % m; } H %= m; ans = (ans * H) % m; } else { int h = jed[f] - jed[e]; long long H = 0; for(int i=0; i<=min(il[e], il[f] - h); ++i) { H += (bin(il[e], i) * bin(il[f], i + h)) % m; } H %= m; ans = (ans * H) % m; } } nr[e] = nr[f] = 0; } } for(int i=1; i<=N; ++i) { if(nr[i] == 1) ans = (ans * bin(il[i], jed[i])) % m; else if(nr[i] == 2) ans = (ans * pot(il[i] - 1)) % m; } cout<<ans<<endl; return 0; }
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 117 118 119 120 121 122 123 124 125 | #include<iostream> #include<algorithm> #include<vector> #include<cmath> #include<ctime> #include<cstring> #include<limits> #include<complex> using namespace std; const long long m = 1000000007; const int c = 200000; long long factorial[c+1]; long long inv(long long a) { return a <= 1 ? a : m - (long long)(m/a) * inv(m % a) % m; } long long bin(int n, int k) { return factorial[n] * inv(factorial[k] * factorial[n - k] % m) % m; } long long pot(int n) { long long ans = 1; for(int i=0; i<n; ++i) ans = (ans * 2) % m; return ans; } struct FAU { int *p, *w; FAU(int n) : p(new int[n]), w(new int[n]) { for(int x=0; x<n; ++x) p[x] = w[x] = -1; } ~FAU() { delete[]p; delete[]w; } int Find(int x) { return (p[x] < 0) ? x : p[x] = Find(p[x]); } void Union(int x, int y) { if((x = Find(x)) == (y = Find(y))) return; if(w[x] > w[y]) p[y] = x; else p[x] = y; if(w[x] == w[y]) w[y]++; } }; int main() { ios::sync_with_stdio(0); factorial[0] = 1; for (int i = 1; i <= c; i++) { factorial[i] = factorial[i - 1] * i % m; } int N,M; cin>>N>>M; int Z[c+1],a[c*2],b[c*2]; for(int i=1; i<=N; ++i) cin>>Z[i]; vector<int> L[c+1]; for(int i=0; i<M; ++i) { cin>>a[i]>>b[i]; L[a[i]].push_back(b[i]); L[b[i]].push_back(a[i]); } FAU fau(N+1); for(int i=1; i<=N; ++i) { int r = L[i].size(); for(int j=1; j<r; ++j) fau.Union(L[i][0], L[i][j]); } int nr[c+1]; int il[c+1]; int jed[c+1]; for(int i=0; i<=N; ++i) nr[i] = il[i] = jed[i] = 0; for(int i=1; i<=N; ++i) { int pom = fau.Find(i); nr[pom] = 1; il[pom]++; if(Z[i] == 1) jed[pom]++; } for(int i=0; i<M; ++i) { if(fau.Find(a[i]) == fau.Find(b[i])) { nr[fau.Find(a[i])] = 2; } } long long ans = 1; for(int i=0; i<M; ++i) { int e,f; e = fau.Find(a[i]); f = fau.Find(b[i]); if(e != f && nr[e]*nr[f] != 0) { if(nr[e] == 2 || nr[f] == 2) { ans = (ans * pot(il[e]+il[f]-1)) % m; } else { if(jed[e] > jed[f]) { int h = jed[e] - jed[f]; long long H = 0; for(int i=0; i<=min(il[f], il[e] - h); ++i) { H += (bin(il[f], i) * bin(il[e], i + h)) % m; } H %= m; ans = (ans * H) % m; } else { int h = jed[f] - jed[e]; long long H = 0; for(int i=0; i<=min(il[e], il[f] - h); ++i) { H += (bin(il[e], i) * bin(il[f], i + h)) % m; } H %= m; ans = (ans * H) % m; } } nr[e] = nr[f] = 0; } } for(int i=1; i<=N; ++i) { if(nr[i] == 1) ans = (ans * bin(il[i], jed[i])) % m; else if(nr[i] == 2) ans = (ans * pot(il[i] - 1)) % m; } cout<<ans<<endl; return 0; } |