Submission #3773584


Source Code Expand

#include <bits/stdc++.h>

using namespace std;
#ifdef _DEBUG
#define _GLIBCXX_DEBUG
#include "dump.hpp"
#else
#define dump(...)
#endif

#define int long long
#define ll long long
#define ll1 1ll
#define ONE 1ll
#define DBG 1
#define rep(i, a, b) for (int i = (a); i < (b); i++)
#define rrep(i, a, b) for (int i = (b)-1; i >= (a); i--)
#define loop(n) rep(loop, (0), (n))
#define all(c) begin(c), end(c)
const int INF =
    sizeof(int) == sizeof(long long) ? 0x3f3f3f3f3f3f3f3fLL : 0x3f3f3f3f;
const int MOD = (int)(1e9) + 7;
const double PI = acos(-1);
const double EPS = 1e-9;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
using pii = pair<int, int>;
// template<class T> ostream &operator<<(ostream &os,T &t){dump(t);return os;}
template <typename T, typename S>
istream &operator>>(istream &is, pair<T, S> &p) {
  is >> p.first >> p.second;
  return is;
}
template <typename T, typename S>
ostream &operator<<(ostream &os, pair<T, S> &p) {
  os << p.first << " " << p.second;
  return os;
}

template <typename T> void printvv(const vector<vector<T>> &v) {
  cerr << endl;
  rep(i, 0, v.size()) rep(j, 0, v[i].size()) {
    if (typeid(v[i][j]).name() == typeid(INF).name() and v[i][j] == INF) {
      cerr << "INF";
    } else
      cerr << v[i][j];
    cerr << (j == v[i].size() - 1 ? '\n' : ' ');
  }
  cerr << endl;
}
/*
   typedef __int128_t Int;
   std::ostream &operator<<(std::ostream &dest, __int128_t value) {
   std::ostream::sentry s(dest);
   if (s) {
   __uint128_t tmp = value < 0 ? -value : value;
   char buffer[128];
   char *d = std::end(buffer);
   do {
   --d;
 *d = "0123456789"[tmp % 10];
 tmp /= 10;
 } while (tmp != 0);
 if (value < 0) {
 --d;
 *d = '-';
 }
 int len = std::end(buffer) - d;
 if (dest.rdbuf()->sputn(d, len) != len) {
 dest.setstate(std::ios_base::badbit);
 }
 }
 return dest;
 }

 __int128 parse(string &s) {
 __int128 ret = 0;
 for (int i = 0; i < s.length(); i++)
 if ('0' <= s[i] && s[i] <= '9')
 ret = 10 * ret + s[i] - '0';
 return ret;
 }
 */

#ifndef _DEBUG
#define printvv(...)
#endif
void YES(bool f) { cout << (f ? "YES" : "NO") << endl; }
void Yes(bool f) { cout << (f ? "Yes" : "No") << endl; }
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> class mat : public vector<vector<T>> {
private:
  int r, c; //行,列
public:
  int row() const { return r; }
  int column() const { return c; }
  mat(int n, int m, T val = 0) {
    r = n, c = m;
    for (int i = 0; i < n; i++) {
      this->push_back(vector<T>(m, val));
    }
  }
  mat operator+(const mat &another) {
    if (r != another.r && c != another.c) {
      cout << "足し算失敗(サイズ不一致)" << endl;
      exit(1);
    }
    mat<T> X(r, c);
    for (int i = 0; i < r; i++) {
      for (int j = 0; j < c; j++) {
        X[i][j] = (*this)[i][j] + another[i][j];
      }
    }
    return X;
  }
  mat operator+(const T val) {
    mat<T> X(r, c);
    for (int i = 0; i < r; i++) {
      for (int j = 0; j < c; j++) {
        X[i][j] = (*this)[i][j] + val;
      }
    }
    return X;
  }
  mat operator-(const mat &another) {
    if (r != another.r && c != another.c) {
      cout << "引き算失敗(サイズ不一致)" << endl;
      exit(1);
    }
    mat<T> X(r, c);
    for (int i = 0; i < r; i++) {
      for (int j = 0; j < c; j++) {
        X[i][j] = (*this)[i][j] - another[i][j];
      }
    }
    return X;
  }
  mat operator-(const T val) {
    mat<T> X(r, c);
    for (int i = 0; i < r; i++) {
      for (int j = 0; j < c; j++) {
        X[i][j] = (*this)[i][j] - val;
      }
    }
    return X;
  }
  vector<T> operator*(const vector<T> &another) {
    if (c != (int)another.size()) {
      cout << "掛け算失敗(サイズ不一致)" << endl;
      exit(1);
    }
    vector<T> vec(r, 0);
    for (int i = 0; i < r; i++) {
      for (int j = 0; j < c; j++) {
        vec[i] += (*this)[i][j] * another[j];
      }
    }
    return vec;
  }
  mat operator*(const mat &another) {
    if (c != another.r) {
      cout << "掛け算失敗(サイズ不一致)" << endl;
      exit(1);
    }
    mat<T> X(r, another.c);
    for (int i = 0; i < r; i++) {
      for (int k = 0; k < c; k++) {
        for (int j = 0; j < (another.c); j++) {
          X[i][j] += (*this)[i][k] * another[k][j];
        }
      }
    }
    return X;
  }
  mat operator-() {
    mat<T> X(r, c);
    for (int i = 0; i < r; i++) {
      for (int j = 0; j < c; j++) {
        X[i][j] = -(*this)[i][j];
      }
    }
    return X;
  }
  int rank() {
    int res = 0;
    mat B(r, c);
    for (int i = 0; i < r; i++) {
      for (int j = 0; j < c; j++) {
        B[i][j] = (*this)[i][j];
      }
    }
    for (int i = 0; i < c; i++) {
      if (res == r)
        return res;
      int pivot = res;
      for (int j = res + 1; j < r; j++) {
        if (abs(B[j][i]) > abs(B[pivot][i])) {
          pivot = j;
        }
      }
      if (abs(B[pivot][i]) < EPS)
        continue;
      swap(B[pivot], B[res]);
      for (int j = i + 1; j < c; j++) {
        B[res][j] /= B[res][i];
      }
      for (int j = res + 1; j < r; j++) {
        for (int k = i + 1; k < c; k++) {
          B[j][k] -= B[res][k] * B[j][i];
        }
      }
      res++;
    }
    return res;
  }
  T det() {
    if (r != c) {
      cout << "正方行列でない(行列式定義不可)" << endl;
      exit(1);
    }
    T ans = 1;
    mat B(r, r);
    for (int i = 0; i < r; i++) {
      for (int j = 0; j < r; j++) {
        B[i][j] = (*this)[i][j];
      }
    }
    for (int i = 0; i < r; i++) {
      for (int j = i + 1; j < r; j++) {
        // 行i,jをgcdしている!
        for (; B[j][i] != 0; ans = -ans) {
          // 行をswapしているので(-1)倍する
          T tm = B[i][i] / B[j][i];
          for (int k = i; k < r; k++) {
            T t = B[i][k] - tm * B[j][k];
            B[i][k] = B[j][k];
            B[j][k] = t;
          }
        }
      }
      ans *= B[i][i];
    }
    return ans;
  }
  mat inverse() {
    if (r != c) {
      cout << "正方行列でない(逆行列定義不可)" << endl;
      exit(1);
    }
    mat B(r, 2 * r);
    for (int i = 0; i < r; i++) {
      for (int j = 0; j < r; j++) {
        B[i][j] = (*this)[i][j];
      }
    }
    for (int i = 0; i < r; i++) {
      B[i][r + i] = 1;
    }
    for (int i = 0; i < r; i++) {
      int pivot = i;
      for (int j = i; j < r; j++) {
        if (abs(B[j][i]) > abs(B[pivot][i])) {
          pivot = j;
        }
      }
      if (abs(B[pivot][i]) < EPS) {
        cout << "解なしor不定" << endl;
        exit(1);
      }
      swap(B[i], B[pivot]);
      for (int j = i + 1; j <= 2 * r; j++) {
        B[i][j] /= B[i][i];
      }
      for (int j = 0; j < r; j++) {
        if (i != j) {
          for (int k = i + 1; k <= 2 * r; k++) {
            B[j][k] -= B[j][i] * B[i][k];
          }
        }
      }
    }
    mat res(r, r);
    for (int i = 0; i < r; i++) {
      for (int j = 0; j < r; j++) {
        res[i][j] = B[i][r + j];
      }
    }
    return res;
  }
  void print() {
    for (int i = 0; i < r; i++) {
      for (int j = 0; j < (c - 1); j++) {
        cout << (*this)[i][j] << ",";
      }
      cout << (*this)[i][c - 1] << endl;
    }
  }
};

template <typename T> vector<T> eq_solve(const mat<T> &A, const vector<T> &b) {
  if (A.row() != A.column()) {
    cout << "正方行列でない(解なしor不定)" << endl;
    exit(1);
  }
  int n = A.row();
  mat<T> B(n, n + 1);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      B[i][j] = A[i][j];
    }
  }
  for (int i = 0; i < n; i++) {
    B[i][n] = b[i];
  }
  for (int i = 0; i < n; i++) {
    int pivot = i;
    for (int j = i; j < n; j++) {
      if (abs(B[j][i]) > abs(B[pivot][i])) {
        pivot = j;
      }
    }
    if (abs(B[pivot][i]) < EPS) {
      cout << "解なしor不定" << endl;
      exit(1);
    }
    swap(B[i], B[pivot]);
    for (int j = i + 1; j <= n; j++) {
      B[i][j] /= B[i][i];
    }
    for (int j = 0; j < n; j++) {
      if (i != j) {
        for (int k = i + 1; k <= n; k++) {
          B[j][k] -= B[j][i] * B[i][k];
        }
      }
    }
  }
  vector<T> res(n);
  for (int i = 0; i < n; i++) {
    res[i] = B[i][n];
  }
  return res;
}

template <typename T> mat<T> pow(mat<T> A, long long cnt) {
  if (A.row() != A.column()) {
    cout << "累乗不可" << endl;
  }
  int n = A.row();
  mat<T> B(n, n);
  for (int i = 0; i < n; i++) {
    B[i][i] = 1;
  }
  while (cnt > 0) {
    if (cnt & 1) {
      B = B * A;
    }
    A = A * A;
    cnt >>= 1;
  }
  return B;
}

template <typename T> mat<T> mod_mul(mat<T> &A, mat<T> &B) {
  if (A.column() != B.row()) {
    cout << "掛け算失敗(サイズ不一致)" << endl;
    exit(1);
  }
  mat<T> X(A.row(), B.column());
  for (int i = 0; i < A.row(); i++) {
    for (int k = 0; k < A.column(); k++) {
      for (int j = 0; j < B.column(); j++) {
        X[i][j] = (X[i][j] + A[i][k] * B[k][j]) % MOD;
      }
    }
  }
  return X;
}

template <typename T> mat<T> mod_pow(mat<T> A, long long cnt) {
  if (A.row() != A.column()) {
    cout << "累乗不可" << endl;
  }
  int n = A.row();
  mat<T> B(n, n);
  for (int i = 0; i < n; i++) {
    B[i][i] = 1;
  }
  while (cnt > 0) {
    if (cnt & 1) {
      B = mod_mul(B, A);
    }
    A = mod_mul(A, A);
    cnt >>= 1;
  }
  return B;
}

struct SCC {
  int V;
  vector<vector<int>> G, rG, SC;
  vector<int> vs, cmp; // post order, topological order
  vector<bool> used;

  SCC() {}
  SCC(int V) : V(V), G(V), rG(V), used(V), cmp(V) {}
  void add_arc(int s, int t) {
    G[s].push_back(t);
    rG[t].push_back(s);
  }
  void dfs(int v) {
    used[v] = true;
    for (int i : G[v]) {
      if (not used[i])
        dfs(i);
    }
    vs.push_back(v);
  }
  void rdfs(int v, int k) {
    used[v] = true;
    cmp[v] = k;
    for (int i : rG[v]) {
      if (not used[i])
        rdfs(i, k);
    }
  }
  int scc() {
    fill(all(used), false);
    vs.clear();
    SC.clear();
    rep(v, 0, V) {
      if (not used[v])
        dfs(v);
    }
    fill(all(used), false);
    int k = 0;
    rrep(i, 0, vs.size()) {
      if (not used[vs[i]])
        rdfs(vs[i], k++);
    }
    SC.resize(k);
    rep(i, 0, V) { SC[cmp[i]].emplace_back(i); }
    rep(i, 0, SC.size()) { sort(all(SC[i])); }
    return k;
  }
  void solve() {
    vector<double> pr(V);
    scc();
    rep(k, 0, SC.size()) {
      int n = SC[k].size();

      set<int> st;
      map<int, int> rev;
      rep(i, 0, SC[k].size()) {
        st.insert(SC[k][i]);
        rev[SC[k][i]] = i;
      }

      mat<double> m(n, n, 0), I(n, n);
      vector<double> b(n, 0.1);
      rep(i, 0, n) I[i][i] = 1;
      rep(i, 0, n) {
        for (auto v : rG[SC[k][i]]) {
          if (st.count(v)) {
            m[i][rev[v]] = 0.9 / G[v].size();
          } else {
            b[i] += pr[v] * 0.9 / G[v].size();
          }
        }
      }
      dump(m);

      auto ans = eq_solve(I - m, b);
      rep(i, 0, n) { pr[SC[k][i]] = ans[i]; }
    }
    for (auto x : pr)
      cout << x << endl;
  }
};
signed main(signed argc, char *argv[]) {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(12);

  int N, M;
  cin >> N >> M;
  SCC g(N);
  loop(M) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    g.add_arc(a, b);
  }
  g.solve();

  return 0;
}

Submission Info

Submission Time
Task E - Page Rank
User norma
Language C++14 (GCC 5.4.1)
Score 100
Code Size 11996 Byte
Status AC
Exec Time 40 ms
Memory 4012 KB

Judge Result

Set Name All
Score / Max Score 100 / 100
Status
AC × 25
Set Name Test Cases
All 10_sample_01.txt, 10_sample_02.txt, 20-random_small-00.txt, 20-random_small-01.txt, 20-random_small-02.txt, 20-random_small-03.txt, 20-random_small-04.txt, 20-random_small-05.txt, 20-random_small-06.txt, 20-random_small-07.txt, 20-random_small-08.txt, 20-random_small-09.txt, 30-random_large-00.txt, 30-random_large-01.txt, 30-random_large-02.txt, 30-random_large-03.txt, 30-random_large-04.txt, 30-random_large-05.txt, 30-random_large-06.txt, 30-random_large-07.txt, 30-random_large-08.txt, 30-random_large-09.txt, 40-random_max-00.txt, 40-random_max-01.txt, 40-random_max-02.txt
Case Name Status Exec Time Memory
10_sample_01.txt AC 2 ms 256 KB
10_sample_02.txt AC 2 ms 256 KB
20-random_small-00.txt AC 3 ms 512 KB
20-random_small-01.txt AC 2 ms 512 KB
20-random_small-02.txt AC 2 ms 256 KB
20-random_small-03.txt AC 3 ms 640 KB
20-random_small-04.txt AC 2 ms 256 KB
20-random_small-05.txt AC 2 ms 384 KB
20-random_small-06.txt AC 2 ms 256 KB
20-random_small-07.txt AC 3 ms 640 KB
20-random_small-08.txt AC 3 ms 524 KB
20-random_small-09.txt AC 2 ms 384 KB
30-random_large-00.txt AC 4 ms 512 KB
30-random_large-01.txt AC 21 ms 3456 KB
30-random_large-02.txt AC 32 ms 1664 KB
30-random_large-03.txt AC 23 ms 1408 KB
30-random_large-04.txt AC 12 ms 768 KB
30-random_large-05.txt AC 15 ms 1024 KB
30-random_large-06.txt AC 40 ms 4012 KB
30-random_large-07.txt AC 14 ms 896 KB
30-random_large-08.txt AC 30 ms 1664 KB
30-random_large-09.txt AC 33 ms 1920 KB
40-random_max-00.txt AC 37 ms 2048 KB
40-random_max-01.txt AC 37 ms 2048 KB
40-random_max-02.txt AC 37 ms 2048 KB