Problem p02728 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
using namespace std;

#define DIV 1000000007

long long N;

vector<long long> tree[200005];
//             a -> bの下にある子供の数
map<pair<long long, long long>, long long> ch;

//             a -> bの下にある子供のパターン
map<pair<long long, long long>, long long> memo;

long long outpat[200005];

long long kaidan[200010];

void kaical(long long n) {
  kaidan[0] = 1;
  for (long long i = 1; i < 200005; i++) {
    kaidan[i] = kaidan[i - 1] * i;
    kaidan[i] %= DIV;
  }
}

long long modpow(long long ori, long long po) {
  long long res = 1;
  while (po > 0) {
    if (po & 1) {
      res *= ori;
      res %= DIV;
    }
    ori *= ori;
    ori %= DIV;
    po >>= 1;
  }
  return res;
}

pair<long long, long long> dfs(long long pa, long long cur) {
  //              nums, pat
  vector<pair<long long, long long>> nums;
  for (long long i = 0; i < tree[cur].size(); i++) {
    if (pa != tree[cur][i]) {
      nums.push_back(dfs(cur, tree[cur][i]));
    }
  }

  long long chs = 0;
  long long ans = 1;
  for (long long i = 0; i < nums.size(); i++) {
    chs += nums[i].first;
    ans *= nums[i].second;
    ans %= DIV;
    ans *= modpow(kaidan[nums[i].first], DIV - 2);
    ans %= DIV;
  }
  ans *= kaidan[chs];
  ans %= DIV;

  // 自分
  chs++;

  if (pa != -1) {
    ch[make_pair(pa, cur)] = chs;
    memo[make_pair(pa, cur)] = ans;

    // cout << "dfs " << pa << " -> " << cur << " ans = " << ans << " chs = " <<
    // chs << endl;
    outpat[pa] *= ans;
    outpat[pa] %= DIV;
    outpat[pa] *= modpow(kaidan[chs], DIV - 2);
    outpat[pa] %= DIV;
  }
  return make_pair(chs, ans);
}

void dfs2(long long to, long long from) {
  long long ans = 1;
  if (to != -1) {
    /*
    long long ans = 1;
    long long chnum = 0;
    for(long long i = 0; i < tree[to].size(); i++) {
            if(from != tree[to][i]) {
                    chnum += ch[make_pair(to, tree[to][i])];
                    ans *= memo[make_pair(to, tree[to][i])];
                    ans %= DIV;
                    ans *= modpow(kaidan[ch[make_pair(to, tree[to][i])]], DIV -
    2); ans %= DIV;
            }
    }
    ans *= kaidan[chnum];
    ans %= DIV;

    ch[make_pair(from, to)] = chnum + 1;
    memo[make_pair(from, to)] = ans;
    */

    // cout << "dfs2 outpat[" << to << "] = " << outpat[to] << endl;
    // toから外に出る奴
    //  (pat/(ch!)) の 積
    ans *= outpat[to];
    ans %= DIV;

    // to -> from の物(pat/ch!)でわる
    ans *= kaidan[ch[make_pair(to, from)]];
    ans %= DIV;
    ans *= modpow(memo[make_pair(to, from)], DIV - 2);
    ans %= DIV;

    long long chs = N;
    chs -= ch[make_pair(to, from)];
    // cout << "dfs2 " << to << " <- "  << from << " chs = " << chs << endl;
    // cout << "tmp ans = " << ans << endl;

    // toのch!をかける
    ans *= kaidan[chs - 1];
    ans %= DIV;

    ch[make_pair(from, to)] = chs;
    memo[make_pair(from, to)] = ans;

    outpat[from] *= ans;
    outpat[from] %= DIV;
    outpat[from] *= modpow(kaidan[chs], DIV - 2);
    outpat[from] %= DIV;
  }

  for (long long i = 0; i < tree[from].size(); i++) {
    if (tree[from][i] != to) {
      dfs2(from, tree[from][i]);
    }
  }

  return;
}

int main() {
  cin >> N;
  for (long long i = 0; i < N - 1; i++) {
    long long a, b;
    cin >> a >> b;
    a--;
    b--;
    tree[a].push_back(b);
    tree[b].push_back(a);
    outpat[i] = 1;
  }
  outpat[N - 1] = 1;

  kaical(N + 5);
  dfs(-1, 0);
  dfs2(-1, 0);

  // for(auto item: ch) {
  //	cout << item.first.first << " -> " << item.first.second << " ch = " <<
  //item.second << endl;
  // }

  // for(auto item: memo) {
  //	cout << item.first.first << " -> " << item.first.second << " memo = " <<
  //item.second << endl;
  // }

  for (long long i = 0; i < N; i++) {
    long long ans = kaidan[N - 1];
    for (long long j = 0; j < tree[i].size(); j++) {
      ans *= memo[make_pair(i, tree[i][j])];
      ans %= DIV;
      ans *= modpow(kaidan[ch[make_pair(i, tree[i][j])]], DIV - 2);
      ans %= DIV;
    }
    cout << ans << endl;
  }
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

#define DIV 1000000007

long long N;

vector<long long> tree[200005];
//             a -> bの下にある子供の数
map<pair<long long, long long>, long long> ch;

//             a -> bの下にある子供のパターン
map<pair<long long, long long>, long long> memo;

long long outpat[200005];

long long kaidan[200010];

void kaical(long long n) {
  kaidan[0] = 1;
  for (long long i = 1; i < 200005; i++) {
    kaidan[i] = kaidan[i - 1] * i;
    kaidan[i] %= DIV;
  }
}

long long modpow(long long ori, long long po) {
  long long res = 1;
  while (po > 0) {
    if (po & 1) {
      res *= ori;
      res %= DIV;
    }
    ori *= ori;
    ori %= DIV;
    po >>= 1;
  }
  return res;
}

pair<long long, long long> dfs(long long pa, long long cur) {
  //              nums, pat
  vector<pair<long long, long long>> nums;
  for (long long i = 0; i < tree[cur].size(); i++) {
    if (pa != tree[cur][i]) {
      nums.push_back(dfs(cur, tree[cur][i]));
    }
  }

  long long chs = 0;
  long long ans = 1;
  for (long long i = 0; i < nums.size(); i++) {
    chs += nums[i].first;
    ans *= nums[i].second;
    ans %= DIV;
    ans *= modpow(kaidan[nums[i].first], DIV - 2);
    ans %= DIV;
  }
  ans *= kaidan[chs];
  ans %= DIV;

  // 自分
  chs++;

  if (pa != -1) {
    ch[make_pair(pa, cur)] = chs;
    memo[make_pair(pa, cur)] = ans;

    // cout << "dfs " << pa << " -> " << cur << " ans = " << ans << " chs = " <<
    // chs << endl;
    outpat[pa] *= ans;
    outpat[pa] %= DIV;
    outpat[pa] *= modpow(kaidan[chs], DIV - 2);
    outpat[pa] %= DIV;
  }
  return make_pair(chs, ans);
}

void dfs2(long long to, long long from) {
  long long ans = 1;
  if (to != -1) {
    long long ans = 1;
    long long chnum = 0;
    for (long long i = 0; i < tree[to].size(); i++) {
      if (from != tree[to][i]) {
        chnum += ch[make_pair(to, tree[to][i])];
        ans *= memo[make_pair(to, tree[to][i])];
        ans %= DIV;
        ans *= modpow(kaidan[ch[make_pair(to, tree[to][i])]], DIV - 2);
        ans %= DIV;
      }
    }
    ans *= kaidan[chnum];
    ans %= DIV;

    ch[make_pair(from, to)] = chnum + 1;
    memo[make_pair(from, to)] = ans;

    /*

    //cout << "dfs2 outpat[" << to << "] = " << outpat[to] << endl;
    //toから外に出る奴
    // (pat/(ch!)) の 積
    ans *= outpat[to];
    ans %= DIV;

    // to -> from の物(pat/ch!)でわる
    ans *= kaidan[ch[make_pair(to, from)]];
    ans %= DIV;
    ans *= modpow(memo[make_pair(to, from)], DIV - 2);

    long long chs = N;
    chs -= ch[make_pair(to, from)];
    cout << "dfs2 " << to << " <- "  << from << " chs = " << chs << endl;
    //cout << "tmp ans = " << ans << endl;

    //toのch!をかける
    ans *= kaidan[chs-1];
    ans %= DIV;

    ch[make_pair(from, to)] = chs;
    memo[make_pair(from, to)] = ans;

    outpat[from] *= ans;
    outpat[from] %= DIV;
    outpat[from] *= modpow(kaidan[chs], DIV-2);
    outpat[from] %= DIV;
    */
  }

  for (long long i = 0; i < tree[from].size(); i++) {
    if (tree[from][i] != to) {
      dfs2(from, tree[from][i]);
    }
  }

  return;
}

int main() {
  cin >> N;
  for (long long i = 0; i < N - 1; i++) {
    long long a, b;
    cin >> a >> b;
    a--;
    b--;
    tree[a].push_back(b);
    tree[b].push_back(a);
    outpat[i] = 1;
  }
  outpat[N - 1] = 1;

  kaical(N + 5);
  dfs(-1, 0);
  dfs2(-1, 0);

  // for(auto item: ch) {
  //	cout << item.first.first << " -> " << item.first.second << " ch = " <<
  //item.second << endl;
  // }

  // for(auto item: memo) {
  //	cout << item.first.first << " -> " << item.first.second << " memo = " <<
  //item.second << endl;
  // }

  for (long long i = 0; i < N; i++) {
    long long ans = kaidan[N - 1];
    for (long long j = 0; j < tree[i].size(); j++) {
      ans *= memo[make_pair(i, tree[i][j])];
      ans %= DIV;
      ans *= modpow(kaidan[ch[make_pair(i, tree[i][j])]], DIV - 2);
      ans %= DIV;
    }
    cout << ans << endl;
  }
}