Advertisement
_ash__

Untitled

Dec 29th, 2020
748
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.43 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. #define Gene template< class
  5. #define Rics printer& operator,
  6. Gene c> struct rge{c b, e;};
  7. Gene c> rge<c> range(c i, c j){ return {i, j};}
  8. struct printer{
  9.     ~printer(){cerr<<endl;}
  10.     Gene c >Rics(c x){ cerr<<boolalpha<<x; return *this;}
  11.     Rics(string x){cerr<<x;return *this;}
  12.     Gene c, class d >Rics(pair<c, d> x){ return *this,"(",x.first,", ",x.second,")";}
  13.     Gene ... d, Gene ...> class c >Rics(c<d...> x){ return *this, range(begin(x), end(x));}
  14.     Gene c >Rics(rge<c> x){
  15.         *this,"["; for(auto it = x.b; it != x.e; ++it)
  16.             *this,(it==x.b?"":", "),*it; return *this,"]";}
  17. };
  18. #define debug() cerr<<"LINE "<<__LINE__<<" >> ", printer()
  19. #define dbg(x) "[",#x,": ",(x),"] "
  20. mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
  21. int my_rand(int l, int r) {
  22.     return uniform_int_distribution<int>(l, r) (rng);
  23. }
  24.  
  25. int P(int u, vector<int> &par) {
  26.     return par[u] = (par[u]^u ? P(par[u], par) : u);
  27. }
  28.  
  29. const int N = 3e6 + 100;
  30. int mod = 1e9 + 9;
  31.  
  32. namespace Combi {
  33.     int fact[N], inv[N];
  34.  
  35.     int bm(int b, int p, int m) {
  36.         if(p == 0) return 1%m;
  37.         int t = bm(b,p/2,m);
  38.         t = (1ll*t*t)%m;
  39.         if(p&1) return 1ll*t*b%m;
  40.         return t;
  41.     }
  42.  
  43.     int C(int n, int r) {
  44.         if(n < 0 or r < 0 or r > n) return 0;
  45.         int ret = 1ll*fact[n]*inv[r]%mod;
  46.         ret = 1ll*ret*inv[n-r]%mod;
  47.         return ret;
  48.     }
  49.     // X1 + X2 + ... + Xvar = Sum
  50.     int no_of_eqns(int var, int sum) {
  51.         return C(sum+var-1,var-1); // Xi >= 0
  52.         // return C(sum-1,var-1); // Xi > 0
  53.     }
  54.     /// divide a set of n size into k non-empty sets O(klogn)
  55.     int stirling(int n, int k)  {
  56.         int ans = 0;
  57.         for(int i = 0; i <= k; i++) {
  58.             int x = 1ll*C(k,i)*bm(k-i,n,mod)%mod;
  59.             if(i&1) ans -= x;
  60.             else ans += x;
  61.             ans %= mod;
  62.             ans += mod;
  63.             ans %= mod;
  64.         }
  65.         ans = 1ll*ans*inv[k]%mod;
  66.         return ans;
  67.     }
  68.  
  69.     void init() {
  70.         fact[0] = 1;
  71.         for(int i = 1; i < N; i++) {
  72.             fact[i] = 1ll*fact[i-1]*i%mod;
  73.         }
  74.         inv[N-1] = bm(fact[N-1], mod-2, mod);
  75.         for(int i = N-2; i >= 0; i--) {
  76.             inv[i] = 1ll*inv[i+1]*(i+1)%mod;
  77.         }
  78.     }
  79. }
  80.  
  81.  
  82.  
  83. int main() {
  84. //    freopen("in.txt", "r", stdin);
  85.     ios::sync_with_stdio(0);
  86.     cin.tie(0);
  87.  
  88.     Combi::init();
  89.  
  90.     int n, m;
  91.     cin >> n >> m;
  92.     map<int,int> ids;
  93.     int id = 0;
  94.     vector<pair<int,int>> edges[2];
  95.     for(int i = 0; i < m; i++) {
  96.         int u, v, c;
  97.         cin >> u >> v >> c;
  98.         if(ids.find(u) == ids.end()) ids[u] = id++;
  99.         if(ids.find(v) == ids.end()) ids[v] = id++;
  100.         edges[c].push_back({ids[u], ids[v]});
  101.     }
  102.     int X = edges[1].size();
  103.     int inv6 = Combi::bm(6, mod-2, mod);
  104.     int result = 0;
  105.     for(int mask = 0; mask < (1<<X); mask++) {
  106.         vector<int> par(id), sz(id, 1);
  107.         for(int i = 0; i < id; i++) par[i] = i;
  108.         for(int i = 0; i < edges[0].size(); i++) {
  109.             int u = edges[0][i].first, v = edges[0][i].second;
  110.             u = P(u, par), v = P(v, par);
  111.             if(u == v) continue;
  112.             if(sz[v] > sz[u]) swap(u, v);
  113.             par[v] = u;
  114.             sz[u] += sz[v];
  115.         }
  116.         for(int i = 0; i < X; i++) {
  117.             if(!((mask >> i) & 1)) continue;
  118.             int u = edges[1][i].first, v = edges[1][i].second;
  119.             u = P(u, par), v = P(v, par);
  120.             if(u == v) continue;
  121.             if(sz[v] > sz[u]) swap(u, v);
  122.             par[v] = u;
  123.             sz[u] += sz[v];
  124.         }
  125.         bool ok = true;
  126.         int two = 0, one = 3*n-id;
  127.         for(int i = 0; i < id; i++) {
  128.             if(par[i] != i) continue;
  129.             if(sz[i] > 3) {
  130.                 ok = false;
  131.                 break;
  132.             }
  133.             if(sz[i] == 2) two++;
  134.             if(sz[i] == 1) one++;
  135.         }
  136.         if(ok == false or two > one) continue;
  137.         int ways = 1ll*Combi::C(one, two)*Combi::fact[two]%mod;
  138.         ways = 1ll*ways*Combi::fact[one-two]%mod;
  139.         int inv = Combi::bm(inv6, (one-two)/3, mod);
  140.         ways = 1ll*ways*inv%mod;
  141.         ways = 1ll*ways*Combi::inv[(one-two)/3]%mod;
  142.         if(__builtin_popcount(mask) & 1) result -= ways;
  143.         else result += ways;
  144.  
  145.         result %= mod;
  146.     }
  147.  
  148.     if(result < 0) result += mod;
  149.     cout << result << endl;
  150. }
  151.  
  152.  
  153.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement