#include <bits/stdc++.h>
using namespace std;
constexpr int M = 200'005;
constexpr long long MOD = 1e9+7;
vector<vector<long long>> g(M);
long long stan[M];
long long spojna[M];
pair<pair<long long, long long>, pair<long long, long long>> rozmiary[M];
long long dwudziel[M]; //0 jeszcze nie, 1 da sie, 2 nie da sie
long long kolory[M];
long long silnia[M];
bool odw[M];
long long wielkosc[M];
void dfs(long long v, long long kolor){
spojna[v] = kolor;
wielkosc[kolor]++;
for(auto i:g[v]) if(!spojna[i]) dfs(i, kolor);
}
bool czySieDa = 1;
void dfsk(long long v, long long kolor){
kolory[v] = kolor;
for(auto i:g[v]){
if(kolory[i]==0){
if(kolory[v]==1) dfsk(i, 2);
else dfsk(i, 1);
}
else if(kolory[i]==1 && kolory[v]==1) czySieDa = 0;
else if(kolory[i]==2 && kolory[v]==2) czySieDa = 0;
}
}
void dfskk(long long v){
odw[v] = 1;
if(stan[v]==1 && kolory[v]==1) rozmiary[spojna[v]].first.first++;
else if(stan[v]==1 && kolory[v]==2) rozmiary[spojna[v]].first.second++;
else if(stan[v]==0 && kolory[v]==1) rozmiary[spojna[v]].second.first++;
else if(stan[v]==0 && kolory[v]==2) rozmiary[spojna[v]].second.second++;
for(auto i:g[v]) if(!odw[i]) dfskk(i);
}
long long pote(long long a, long long b){
long long w = 1;
while(b>0){
if (b%2 == 1) w = (a*w)%MOD;
a = (a*a)%MOD;
b/=2;
}
return w%MOD;
}
long long odwrotnosc(long long a){
return pote(a, MOD-2);
}
long long apob(long long a, long long b){
long long temp = 0;
return (((silnia[a]*odwrotnosc(silnia[b]))%MOD)*odwrotnosc(silnia[max(a-b, temp)]))%MOD;
}
int main() {
cin.tie(0)->sync_with_stdio(0);
long long n, m;
cin>>n>>m;
silnia[0] = 1;
for(int i=1; i<=n; i++) silnia[i] = (silnia[i-1]*i)%MOD;
for(int i=1; i<=n; i++) cin>>stan[i];
for(int i=1; i<=m; i++){
int a, b;
cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
long long ileS = 0;
for(int i=1; i<=n; i++) if(!spojna[i]) dfs(i, ++ileS);
for(int i=1; i<=n; i++) if(!kolory[i]){
czySieDa = 1;
dfsk(i, 1);
if(czySieDa==1){
dfskk(i);
dwudziel[spojna[i]] = 2;
}
else dwudziel[spojna[i]] = 1;
}
long long wynik = 1;
long long tempWyn;
for(int i=1; i<=ileS; i++){
if(dwudziel[i]==1 || dwudziel[i]==0) wynik = (wynik*pote(2, wielkosc[i]-1))% MOD;
else{
tempWyn=0;
long long a=rozmiary[i].second.first, b=rozmiary[i].second.second, c=rozmiary[i].first.first, d=rozmiary[i].first.second;
while(b<=rozmiary[i].second.first+rozmiary[i].second.second && d<=rozmiary[i].first.first+rozmiary[i].first.second && a>=0 && c>=0){
tempWyn = (tempWyn + (apob(a+b, a)*apob(c+d, c))) % MOD;
b++, d++, a--, c--;
}
a=rozmiary[i].second.first+1, b=rozmiary[i].second.second-1, c=rozmiary[i].first.first+1, d=rozmiary[i].first.second-1;
while(d>=0 && b>=0){
tempWyn = (tempWyn + (apob(a+b, a)*apob(c+d, c))) % MOD;
a++, c++, b--, d--;
}
wynik = (wynik*tempWyn)%MOD;
}
}
cout<<wynik%MOD<<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 | #include <bits/stdc++.h> using namespace std; constexpr int M = 200'005; constexpr long long MOD = 1e9+7; vector<vector<long long>> g(M); long long stan[M]; long long spojna[M]; pair<pair<long long, long long>, pair<long long, long long>> rozmiary[M]; long long dwudziel[M]; //0 jeszcze nie, 1 da sie, 2 nie da sie long long kolory[M]; long long silnia[M]; bool odw[M]; long long wielkosc[M]; void dfs(long long v, long long kolor){ spojna[v] = kolor; wielkosc[kolor]++; for(auto i:g[v]) if(!spojna[i]) dfs(i, kolor); } bool czySieDa = 1; void dfsk(long long v, long long kolor){ kolory[v] = kolor; for(auto i:g[v]){ if(kolory[i]==0){ if(kolory[v]==1) dfsk(i, 2); else dfsk(i, 1); } else if(kolory[i]==1 && kolory[v]==1) czySieDa = 0; else if(kolory[i]==2 && kolory[v]==2) czySieDa = 0; } } void dfskk(long long v){ odw[v] = 1; if(stan[v]==1 && kolory[v]==1) rozmiary[spojna[v]].first.first++; else if(stan[v]==1 && kolory[v]==2) rozmiary[spojna[v]].first.second++; else if(stan[v]==0 && kolory[v]==1) rozmiary[spojna[v]].second.first++; else if(stan[v]==0 && kolory[v]==2) rozmiary[spojna[v]].second.second++; for(auto i:g[v]) if(!odw[i]) dfskk(i); } long long pote(long long a, long long b){ long long w = 1; while(b>0){ if (b%2 == 1) w = (a*w)%MOD; a = (a*a)%MOD; b/=2; } return w%MOD; } long long odwrotnosc(long long a){ return pote(a, MOD-2); } long long apob(long long a, long long b){ long long temp = 0; return (((silnia[a]*odwrotnosc(silnia[b]))%MOD)*odwrotnosc(silnia[max(a-b, temp)]))%MOD; } int main() { cin.tie(0)->sync_with_stdio(0); long long n, m; cin>>n>>m; silnia[0] = 1; for(int i=1; i<=n; i++) silnia[i] = (silnia[i-1]*i)%MOD; for(int i=1; i<=n; i++) cin>>stan[i]; for(int i=1; i<=m; i++){ int a, b; cin>>a>>b; g[a].push_back(b); g[b].push_back(a); } long long ileS = 0; for(int i=1; i<=n; i++) if(!spojna[i]) dfs(i, ++ileS); for(int i=1; i<=n; i++) if(!kolory[i]){ czySieDa = 1; dfsk(i, 1); if(czySieDa==1){ dfskk(i); dwudziel[spojna[i]] = 2; } else dwudziel[spojna[i]] = 1; } long long wynik = 1; long long tempWyn; for(int i=1; i<=ileS; i++){ if(dwudziel[i]==1 || dwudziel[i]==0) wynik = (wynik*pote(2, wielkosc[i]-1))% MOD; else{ tempWyn=0; long long a=rozmiary[i].second.first, b=rozmiary[i].second.second, c=rozmiary[i].first.first, d=rozmiary[i].first.second; while(b<=rozmiary[i].second.first+rozmiary[i].second.second && d<=rozmiary[i].first.first+rozmiary[i].first.second && a>=0 && c>=0){ tempWyn = (tempWyn + (apob(a+b, a)*apob(c+d, c))) % MOD; b++, d++, a--, c--; } a=rozmiary[i].second.first+1, b=rozmiary[i].second.second-1, c=rozmiary[i].first.first+1, d=rozmiary[i].first.second-1; while(d>=0 && b>=0){ tempWyn = (tempWyn + (apob(a+b, a)*apob(c+d, c))) % MOD; a++, c++, b--, d--; } wynik = (wynik*tempWyn)%MOD; } } cout<<wynik%MOD<<endl; return 0; } |
English