Problem:
J - Tree Reconstruction
Problem Statement
You have a directed graph.
Some non-negative value is assigned on each edge of the graph.
You know that the value of the graph satisfies the
flow conservation law
That is, for every node
v
, the sum of values on edges incoming to
v
equals to
the sum of values of edges outgoing from
v
.
For example, the following directed graph satisfies the flow conservation law.
Suppose that you choose a subset of edges in the graph, denoted by
E'
,
and then you erase all the values on edges other than
E'
.
Now you want to recover the erased values by seeing only remaining information.
Due to the flow conservation law, it may be possible to recover all the erased values.
Your task is to calculate the smallest possible size for such
E'
.
For example, the smallest subset
E'
for the above graph will be green edges in the following figure.
By the flow conservation law, we can recover values on gray edges.
Input
The input consists of multiple test cases.
The format of each test case is as follows.
N
M
s_1
t_1
...
s_M
t_M
The first line contains two integers
N
(
1 \leq N \leq 500
) and
M
(
0 \leq M \leq 3,000
) that indicate the number of nodes and edges, respectively.
Each of the following
M
lines consists of two integers
s_i
and
t_i
(
1 \leq s_i, t_i \leq N
). This means that there is an edge from
s_i
to
t_i
in the graph.
You may assume that the given graph is simple:
There are no self-loops:
s_i \neq t_i
.
There are no multi-edges: for all
i < j
,
\{s_i, t_i\} \neq \{s_j, t_j\}
.
Also, it is guaranteed that each component of the given graph is strongly connected.
That is, for every pair of nodes
v
and
u
, if there exist a path from
v
to
u
, then there exists a path from
u
to
v
.
Note that you are NOT given information of values on edges because it does not effect the answer.
Output
For each test case, print an answer in one line.
Sample Input 1
9 13
1 2
1 3
2 9
3 4
3 5
3 6
4 9
5 7
6 7
6 8
7 9
8 9
9 1
Output for the Sample Input 1
5
Sample Input 2
7 9
1 2
1 3
2 4
3 4
4 5
4 6
5 7
6 7
7 1
Output for the Sample Input 2
3
Sample Input 3
4 4
1 2
2 1
3 4
4 3
Output for the Sample Input 3
2

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

constexpr double eps = 1e-9;

namespace detail {
    bool is_zero(double x) {
        return std::fabs(x) < eps;
    }
}

template <typename T>
class matrix {
public:
    matrix() : matrix(0, 0) {}
    matrix(int r, int c, T init = T())
        : a(r, std::vector<T>(c, init)), row_sz(r), col_sz(c)
    {}

    void init(int r, int c) {
        *this = matrix(r, c);
    }

    matrix& operator+=(matrix const& that) {
        assert(row_sz == that.row_size() && col_sz == that.col_size());
        for(int i = 0; i < row_sz; ++i) {
            for(int j = 0; j < col_sz; ++j) {
                a[i][j] += that[i][j];
            }
        }
    }
    matrix& operator-=(matrix const& that) {
        assert(row_sz == that.row_size() && col_sz == that.col_size());
        for(int i = 0; i < row_sz; ++i) {
            for(int j = 0; j < col_sz; ++j) {
                a[i][j] -= that[i][j];
            }
        }
    }
    matrix& operator*=(matrix const& that) {
        assert(col_sz == that.row_size());
        matrix res(row_sz, that.col_size());
        for(int i = 0; i < row_sz; ++i) {
            for(int k = 0; k < that.col_size(); ++k) {
                for(int j = 0; j < col_sz; ++j) {
                    res[i][j] += a[i][k] * that[k][j];
                }
            }
        }
        return res;
    }
    std::vector<T> operator*(std::vector<T> const& that) {
        assert(col_sz == (int)that.size());
        std::vector<T> res(row_sz);
        for(int i = 0; i < row_sz; ++i) {
            for(int j = 0; j < col_sz; ++j) {
                res[i] += a[i][j] * that[j];
            }
        }
        return res;
    }
    matrix operator+(matrix const& that) const { return matrix(*this) += that; }
    matrix operator-(matrix const& that) const { return matrix(*this) -= that; }
    matrix operator*(matrix const& that) const { return matrix(*this) *= that; }

    bool operator==(matrix const& that) const { return a == that.a; }
    bool operator!=(matrix const& that) const { return !(*this == that); }

    std::vector<T>& operator[](size_t i)             { return a[i]; }
    std::vector<T> const& operator[](size_t i) const { return a[i]; }

    int row_size() const { return row_sz; }
    int col_size() const { return col_sz; }

private:
    std::vector<std::vector<T>> a;
    int row_sz, col_sz;
};

template <typename T>
matrix<T> eye(int n) {
    matrix<T> res(n, n);
    for(int i = 0; i < n; ++i) {
        res[i][i] = 1;
    }
    return res;
}

template <typename T>
int rank_matrix(matrix<T> a) {
    const int R = a.row_size(), C = a.col_size();
    int r = 0;
    for(int i = 0; i < C && r < R; ++i) {
        int pivot = r;
        for(int j = r + 1; j < R; ++j) {
            if(std::abs(a[j][i]) > std::abs(a[pivot][i])) {
                pivot = j;
            }
        }
        std::swap(a[pivot], a[r]);
        if(detail::is_zero(a[r][i])) continue;
        for(int k = C - 1; k >= i; --k) {
            a[r][k] = a[r][k] / a[r][i];
        }
        for(int j = r + 1; j < R; ++j) {
            for(int k = C - 1; k >= i; --k) {
                a[j][k] -= a[r][k] * a[j][i];
            }
        }
        ++r;
    }
    return r;
}

// solve Ax = b
// @note: A must be regular(non-singular)
// @return: x or size 0 vector (when x does not exist or not unique)
template <typename T>
std::vector<T> gauss_jordan(matrix<T> const& A, std::vector<T> const& b) {
    const int n = A.row_size();
    matrix<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(std::abs(B[j][i]) > std::abs(B[pivot][i])) {
                pivot = j;
            }
        }
        std::swap(B[i], B[pivot]);

        if(detail::is_zero(B[i][i])) return std::vector<T>(); // no solution

        for(int j = i + 1; j <= n; ++j) {
            B[i][j] /= B[i][i];
        }
        for(int j = 0; j < n; ++j) {
            if(i == j) continue;
            for(int k = i + 1; k <= n; ++k) {
                B[j][k] -= B[j][i] * B[i][k];
            }
        }
    }

    std::vector<T> x(n);
    for(int i = 0; i < n; ++i) {
        x[i] = B[i][n];
    }
    return x;
}

using namespace std;

int main() {
    int n, m; cin >> n >> m;
    matrix<double> a(n, m);
    for(int i = 0; i < m; ++i) {
        int s, t; cin >> s >> t;
        a[s - 1][i] = 1;
        a[t - 1][i] = -1;
    }
    cout << m - rank_matrix(a) << endl;
}
accuracy: 1
time_ms: 270
memory_kb: 26396
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

const double EPS = 1e-8;
using vec = vector<double>;
using mat = vector<vec>;

// 行列の階数を求める
// 係数行列と拡大係数行列の階数が異なるときは不能
// 係数行列と拡大係数行列の階数が等しく、係数行列の階数と変数の個数が異なるときは不定
// 係数行列と拡大係数行列の階数と変数の個数がすべて等しいときは一意解が存在
int mat_rank(mat A){
    const int R = A.size(), C = A[0].size();
    int ret = 0;
    for(int i=0; ret<R&&i<C; ++i){
        int pivot = ret;
        for(int j=ret+1; j<R; ++j){
            if(abs(A[j][i]) > abs(A[pivot][i])) pivot = j;
        }
        swap(A[pivot], A[ret]);

        if(abs(A[ret][i]) < EPS) continue;

        for(int k=C-1; k>=i; --k) A[ret][k] /= A[ret][i];
        for(int j=ret+1; j<R; ++j){
            for(int k=C-1; k>=i; --k) A[j][k] -= A[ret][k]*A[j][i];
        }
        ++ret;
    }
    return ret;
}

int main(){
    int n,m;
    cin >>n >>m;

    mat Ab(n, vec(m+1));
    rep(i,m){
        int s,t;
        cin >>s >>t;
        --s;
        --t;

        Ab[s][i] = -1;
        Ab[t][i] = 1;
    }

    cout << m - mat_rank(Ab) << endl;
    return 0;
}
accuracy: 1
time_ms: 270
memory_kb: 26292
final_rank: 7

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define int long long
#define all(v) (v).begin(), (v).end()
#define resz(v, ...) (v).clear(), (v).resize(__VA_ARGS__)
#define reps(i, m, n) for(int i = (int)(m); i < (int)(n); i++)
#define rep(i, n) reps(i, 0, n)

template<class T1, class T2> void chmin(T1 &a, T2 b){if(a>b)a=b;}
template<class T1, class T2> void chmax(T1 &a, T2 b){if(a<b)a=b;}

typedef pair<int, int> Pi;
typedef tuple<int, int, int> Ti;
typedef vector<int> vint;

const int inf = 1LL << 55;
const int mod = 1e9 + 7;

typedef vector<double> vec;
typedef vector<vec> mat;
const double eps = 1e-8;

mat mul(const mat& A, const mat& B)
{
  mat C(A.size(), vec(B[0].size()));
  for(int i = 0; i < (int)A.size(); i++) {
    for(int j = 0; j < (int)B.size(); j++) {
      for(int k = 0; k < (int)B[0].size(); k++) {
	C[i][k] += A[i][j] * B[j][k];
      }
    }
  }
  return C;
}

mat pow(mat A, int n)
{
  mat B(A.size(), vec(A.size()));
  for(int i = 0; i < (int)A.size(); i++) B[i][i] = 1;
  while(n > 0) {
    if(n & 1) B = mul(B, A);
    A = mul(A, A);
    n >>= 1;
  }
  return B;
}

double det(mat A) {
  const int n = A.size();
  double D = 1;
  for(int i = 0; i < n; i++) {
    int pivot = i;
    for(int j = i+1; j < n; j++) {
      if(abs(A[j][i]) > abs(A[pivot][i])) pivot = j;
    }
    swap(A[pivot], A[i]);
    D *= A[i][i] * (i != pivot ? -1 : 1);
    if(abs(A[i][i]) < eps) break;
    for(int j = i+1; j < n; j++) {
      for(int k = n-1; k >= i; k--) {
	A[j][k] -= A[i][k]*A[j][i] / A[i][i];
      }
    }
  }
  return D;
}

int Rank(mat A) {
  const int n = A.size(), m = A[0].size();
  int r = 0, c = 0;
  for(int i = 0; i < n; i++) {
    int pivot = -1;
    while(c < m) {
      for(int j = i; j < n; j++) {
	if(abs(A[j][c]) > eps) { pivot = j; break; }
      }
      if(~pivot) break;
      c++;
    }
    if(c >= m) break;
    r++;
    swap(A[pivot], A[i]);
    double a = A[i][c];
    for(int j = 0; j < m; j++) A[i][j] /= a;
    for(int j = i+1; j < n; j++) {
      double aa = A[j][c];
      for(int k = 0; k < m; k++) A[j][k] -= aa*A[i][k];
    }
    c++;
  }
  return r;
}

int N, M;
mat A;

signed main()
{
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);

  cin >> N >> M;
  A.resize(N, vec(M));
  rep(i, M) {
    int s, t;
    cin >> s >> t;
    --s, --t;
    A[s][i]++;
    A[t][i]--;
  }

  cout << M - Rank(A) << endl;

  return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 26348
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef vector<double> vec;
typedef vector<vec> mat;
double eps=1e-8;

void gauss_jordan(mat& A){
  int n=A.size();
  int m=A[0].size();
  
  int rank=0;
  
  vector<bool> flg(n,false);
  
  for(int i=0;i<n;i++){
    int pivot=i;
    for(int j=0;j<n;j++){
      if(flg[j])continue;
      if(abs(A[j][i]) > abs(A[pivot][i]))pivot=j;
    }


    
    swap(A[pivot],A[i]);
    
    if(abs(A[i][i]) < eps)continue;
    
    rank++;
    flg[i]=true;
    
    double val=A[i][i];
    for(int j=0;j<m;j++)A[i][j]/=val;
    
    for(int j=0;j<n;j++){
      if(i==j)continue;
      double va=A[j][i];

      for(int k=0;k<m;k++){
        A[j][k]-=A[i][k]*va;
      }
    }
  }
  /*
  cout<<"rank = "<<rank<<endl;
  cout<<" n = "<<n<<endl;
  cout<<" m = "<<m<<endl;

  for(int i=0;i<n;i++){
    for(int j=0;j<m;j++){
      printf("%3d",(int)A[i][j]);
    }
    cout<<endl;
  }

  */
  cout<<m-rank<<endl;
}

int N,M;
int G[500][500];

int main(){
  memset(G,-1,sizeof(G));
  mat A;
  cin>>N>>M;
  if(M==0){
    cout<<0<<endl;
    return 0;
  }
  for(int i=0;i<M;i++){
    int a,b;
    cin>>a>>b;
    a--,b--;
    G[a][b]=i;
  }

  for(int i=0;i<N;i++){
    bool flg=false;
    vec B(M,0);
    for(int j=0;j<N;j++){
      if(G[i][j]==-1)continue;
      int id=G[i][j];
      B[ id ]=1;
      flg=true;
    }
    for(int j=0;j<N;j++){
      if(G[j][i]==-1)continue;
      int id=G[j][i];
      B[ id ]=-1;
      flg=true;
    }
    if(flg)  A.push_back(B);
  }

  while(A.size()<A[0].size()){
    vec B(M,0);
    A.push_back(B);
  }

  gauss_jordan(A);
  return 0;
}
accuracy: 1
time_ms: 6500
memory_kb: 100000
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef vector<double> vec;
typedef vector<vec> mat;
double eps=1e-8;

void gauss_jordan(mat& A){
  int n=A.size();
  int m=A[0].size();
  
  int rank=0;
  
  vector<bool> flg(n,false);
  
  for(int i=0;i<n;i++){
    int pivot=i;
    for(int j=0;j<n;j++){
      if(flg[j])continue;
      if(abs(A[j][i]) > abs(A[pivot][i]))pivot=j;
    }


    
    swap(A[pivot],A[i]);
    
    if(abs(A[i][i]) < eps)continue;
    
    rank++;
    flg[i]=true;
    
    double val=A[i][i];
    for(int j=0;j<m;j++)A[i][j]/=val;
    
    for(int j=0;j<n;j++){
      if(i==j)continue;
      double va=A[j][i];
      for(int k=0;k<m;k++)
        A[j][k]-=A[i][k]*va;
    }
  }
  /*
  cout<<"rank = "<<rank<<endl;
  cout<<" n = "<<n<<endl;
  cout<<" m = "<<m<<endl;

  for(int i=0;i<n;i++){
    for(int j=0;j<m;j++){
      printf("%3d",(int)A[i][j]);
    }
    cout<<endl;
  }

  */
  cout<<m-rank<<endl;
}

int N,M;
int G[500][500];

int main(){
  memset(G,-1,sizeof(G));
  mat A;
  cin>>N>>M;
  if(M==0){
    cout<<0<<endl;
    return 0;
  }
  for(int i=0;i<M;i++){
    int a,b;
    cin>>a>>b;
    a--,b--;
    G[a][b]=i;
  }

  for(int i=0;i<N;i++){
    vec B(M,0);
    for(int j=0;j<N;j++){
      if(G[i][j]==-1)continue;
      int id=G[i][j];
      B[ id ]=1;
    }
    for(int j=0;j<N;j++){
      if(G[j][i]==-1)continue;
      int id=G[j][i];
      B[ id ]=-1;
    }
    A.push_back(B);
  }

  while(A.size()<A[0].size()){
    vec B(M,0);
    A.push_back(B);
  }
  gauss_jordan(A);
  return 0;
}
accuracy: 0.18604651162790697
time_ms: 1980
memory_kb: 32900
final_rank: 13

code_snippet: #include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <cassert>
using namespace std;

using ld = long double;
constexpr ld eps = 1e-8;

#include <cassert>

namespace detail {

bool is_zero(double d) {
    return (std::abs(d) < eps);
}
bool is_zero(long double d) {
    return (std::abs(d) < eps);
}

}

template <typename T>
class matrix {
public:
    matrix() = delete;
    matrix(int r, int c) 
        : v_(r, std::vector<T>(c)),
          row_(r),
          column_(c)
    {}
    matrix(std::vector<std::vector<T>> const& v)
        : v_(v),
          row_(v.size()),
          column_((v.size() == 0 ? 0 : v[0].size()))
    {}
    matrix(matrix const&) = default;
    matrix(matrix&&) = default;
    matrix& operator=(matrix const&) = default;
    matrix& operator=(matrix&&) = default;
    ~matrix() = default;

    std::vector<T>& operator[](unsigned int i) {
        return v_[i];
    }
    const std::vector<T>& operator[](unsigned int i) const {
        return v_[i];
    }
    matrix& operator+=(matrix const& other) {
        assert("matrix operator+: row or column size does not match" && other.row_size() == row_ && other.column_size() == column_);

        for(int i=0; i<row_; ++i) {
            for(int j=0; j<column_; ++j) {
                v_[i][j] += other[i][j];
            }
        }
        return *this;
    }
    matrix& operator-=(matrix const& other) {
        assert("matrix operator-: row or column size does not match" && other.row_size() == row_ && other.column_size() == column_);

        for(int i=0; i<row_; ++i) {
            for(int j=0; j<column_; ++j) {
                v_[i][j] -= other[i][j];
            }
        }
        return *this;
    }

    int row_size() const {
        return row_;
    }
    int column_size() const {
        return column_;
    }

    // for debug
    void print() {
        for(int i=0; i<row_; ++i) {
            for(int j=0; j<column_; ++j) {
                std::cout << v_[i][j];
                if(j != column_ - 1) {
                    std::cout << " ";
                }
            }
            std::cout << std::endl;
        }
    }

private:
    std::vector<std::vector<T>> v_;
    int row_, column_;
};

template <typename T>
matrix<T> operator-(matrix<T> m) {
    for(int i=0; i<m.row_size(); ++i) {
        for(int j=0; j<m.column_size(); ++j) {
            m[i][j] = -m[i][j];
        }
    }
}

template <typename T>
matrix<T> operator+(matrix<T> lhs, matrix<T> const& rhs) {
    lhs += rhs;
    return lhs;
}

template <typename T>
matrix<T> operator-(matrix<T> lhs, matrix<T> const& rhs) {
    lhs -= rhs;
    return lhs;
}

template <typename T>
matrix <T> operator*(matrix<T> const& lhs, matrix<T> const& rhs) {
    assert("matrix operator*: lhs.column_size() != rhs.row_size()" && lhs.column_size() == rhs.row_size());

    matrix<T> ret(lhs.row_size(), rhs.column_size());
    for(int i=0; i<ret.row_size(); ++i) {
        for(int k=0; k<lhs.column_size(); ++k) {
            for(int j=0; j<ret.column_size(); ++j) {
                ret[i][j] += lhs[i][k] * rhs[k][j];
            }
        }
    }
    return ret;
}

template <typename T>
matrix<T> transpose(matrix<T> const& m) {
    const int R = m.row_size(), C = m.column_size();
    matrix<T> ret(C, R);
    for(int i=0; i<C; ++i) {
        for(int j=0; j<R; ++j) {
            ret[i][j] = m[j][i];
        }
    }
    return ret;
}

template <typename T>
int rank_matrix(matrix<T> a) {
    const int r = a.row_size(), c = a.column_size();
    matrix<long double> b(r, c);
    for(int i=0; i<r; ++i) {
        for(int j=0; j<c; ++j) {
            b[i][j] = static_cast<long double>(a[i][j]);
        }
    }
    return rank_matrix<long double>(std::move(b));
}

template <>
int rank_matrix(matrix<long double> a) {
    const int R = a.row_size(), C = a.column_size();
    int r = 0;
    for(int i=0; i<C && r < R; ++i) {
        int pivot = r;
        for(int j=r+1; j<R; ++j) {
            if(std::abs(a[j][i]) > std::abs(a[pivot][i])) {
                pivot = j;
            }
        }
        std::swap(a[pivot], a[r]);
        if(detail::is_zero(a[r][i])) {
            continue;
        }
        for(int k=C-1; k>=i; --k) {
            a[r][k] = a[r][k] / a[r][i];
        }
        for(int j=r+1; j<R; ++j) {
            for(int k=C-1; k>=i; --k) {
                a[j][k] += -a[r][k] * a[j][i];
            }
        }
        ++r;
    }
    return r;
}

// todo: only long double?
template <typename T>
T det(matrix<T> a) {
    const int R = a.row_size(), C = a.column_size();
    matrix<long double> b(R, C);
    for(int i=0; i<R; ++i) {
        for(int j=0; j<C; ++j) {
            b[i][j] = static_cast<long double>(a[i][j]);
        }
    }
    return static_cast<T>(det<long double>(std::move(b)));
}
template <>
long double det(matrix<long double> a) {
    assert("det(): matrix is not square." && a.column_size() == a.row_size());
    const int R = a.row_size(), C = a.column_size();
    long double ret = 1.0;
    for(int i=0; i<R; ++i) {
        int pivot = i;
        for(int j=i+1; j<R; ++j) {
            if(std::abs(a[j][i]) > std::abs(a[pivot][i])) {
                pivot = j;
            }
        }
        std::swap(a[pivot], a[i]);
        ret *= a[i][i] * (i != pivot ? -1.0 : 1.0);
        if(detail::is_zero(a[i][i])) {
            break;
        }
        for(int j=i+1; j<R; ++j) {
            for(int k=C-1; k>=i; --k) {
                a[j][k] -= a[i][k] * a[j][i] / a[i][i];
            }
        }
    }
    return ret;
}

template <typename T>
matrix<T> make_identity_matrix(int n) {
    matrix<T> ret(n, n);
    for(int i=0; i<n; ++i) {
        ret[i][i] = 1;
    }
    return ret;
}

// mulptile mod ver
template <typename T>
matrix<T> mul(matrix<T> const& a, matrix<T> const& b, long long M) {
    int R = a.row_size(), C = b.column_size();
    assert("matrix mul: row and column size does not match" && a.column_size() == b.row_size());
    matrix<T> ret(R, C);
    for(int i=0; i<R; ++i) {
        for(int k=0; k<a.column_size(); ++k) {
            for(int j=0; j<C; ++j) {
                ret[i][j] = (ret[i][j] + ((a[i][k] * b[k][j]) % M)) % M;
            }
        }
    }
    return ret;
}

template <typename T>
matrix<T> pow(matrix<T> x, long long y) {
    assert("matrix pow: matrix is not square" && x.column_size() == x.row_size());
    matrix<T> ret = make_identity_matrix<T>(x.column_size());
    while(y > 0) {
        if(y & 1) {
            ret = ret * x;
        }
        x = x * x;
        y >>= 1;
    }
    return ret;
}

template <typename T>
matrix<T> modpow(matrix<T> x, long long y, long long M) {
    assert("matrix pow: matrix is not square" && x.column_size() == x.row_size());
    matrix<T> ret = make_identity_matrix<T>(x.column_size());
    while(y > 0) {
        if(y & 1) {
            ret = mul(ret, x, M);
        }
        x = mul(x, x, M);
        y >>= 1;
    }
    return ret;
}



// LUP factorization(gauss)
// verified: AOJ1328
// Ax = b
// note: A must be regular(non-singular)
// return: x
//         or size 0 vector (if x does not exist or not unique)
vector<double> gauss_jordan(matrix<double>& A, std::vector<double> const& b) {
    int n = A.row_size();
    matrix<double> 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(std::abs(B[j][i]) > std::abs(B[pivot][i])) {
                pivot = j;
            }
        }
        std::swap(B[i], B[pivot]);
        if(std::abs(B[i][i]) < eps) {
            return std::vector<double>();
        }

        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];
                }
            }
        }
    }

    std::vector<double> x(n);
    for(int i=0; i<n; ++i) {
        x[i] = B[i][n];
    }
    return x;
}



int main() {
    int N, M;
    cin >> N >> M;
    matrix<double> A(N, M);
    for(int i=0; i<M; ++i) {
        int s, t;
        cin >> s >> t;
        s--; t--;
        A[s][i] = 1;
        A[t][i] = -1;
    }
    cout << M - rank_matrix(A) << endl;
}
accuracy: 1
time_ms: 1190
memory_kb: 49852
final_rank: 9

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;
const ld eps = 1e-9;

// < "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\a.txt" > "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\b.txt"

/* verified AOJ1327 One-Dimensional Cellular Automaton
~Matrix~
??????????°????????¨?????????§??????
vector iostream cmath cassert ??????
Matrix a(VV), b(VV);
?????????:a*b
????????????:l*a
???:a+b
???:a-b
??¢???:a.transport()
?????????:a.cofactor()
?????????:a.det()
a???i???j??????:a.get(i,j)???
a???i??????j?????????k?????£??\:set(i,j,k)
????????????a[i][j] (a[i][j]=k)
a???x???:a.pow(x)
n*n?????¬??????E:Matrix(n)
m*n 0??????:Matrix(m,n)
m*n ??¨????´????p?????????:Matrix(m,n,p)
Row???row??§????????????(m*1??????):Matrix(row)
**(??´??°??????)**
????§????:a.triangulate()
?????????:a.rank()
?????????:a.inverse()
//(????????????a.det()?????????a.pre_inverse()??§?±??????? ??´??°???)
??¬??????????¶???????:a.rowReduction()
//??£???????¬?????¨????????§£??????
***
*/

#include <vector>
#include <iostream>
#include <cmath>
#include <cassert>
using namespace std;

typedef ld Elem;
typedef vector<Elem> Row;
typedef vector<Row> VV;

typedef long double ld;
const ld EPS = 1e-11;

const bool isZero(const Elem e) {
	return abs(e) < EPS;
}

struct Matrix {
	VV matrix;
	int n, m;

	Matrix(const VV &matrix_);
	explicit Matrix(int n_);
	explicit Matrix(const Row &row);
	Matrix(int m_, int n_);
	Matrix(int m_, int n_, Elem e);

	const Elem get(const int i, const int j) const;
	void set(const int x, const int y, const Elem k);

	const Matrix operator + (const Matrix &rhs) const;
	const Matrix operator * (const Matrix &rhs) const;
	const Matrix operator - (const Matrix &rhs) const;
	Matrix &operator += (const Matrix &rhs);
	Matrix &operator *= (const Matrix &rhs);
	Matrix &operator -= (const Matrix &rhs);

	Row &operator[](const int x);

	const Matrix transport() const;
	const Matrix pow(int x) const;
	const Matrix cofactor(int x, int y) const;
	const Elem det() const;

	const Matrix triangulate() const;
	const int rank() const;

	//?????????????????¨????????°???(?????????)*(?????????)?????????
	//A:matrix,return det A * A^-1
	const Matrix pre_inverse() const;
	const Matrix inverse() const;
	const Matrix rowReduction() const;
};

const Matrix operator * (const Elem lambda, const Matrix &rhs) {
	Matrix tmp(rhs);
	for (int i = 0; i < rhs.m; i++)
		for (int j = 0; j < rhs.n; j++)
			tmp.set(i, j, tmp.get(i, j) * lambda);
	return tmp;
}

Matrix::Matrix(const VV &matrix_) : matrix(matrix_) {
	m = matrix_.size();
	if (m == 0) n = 0;
	else n = matrix_[0].size();
}
Matrix::Matrix(int n_) : m(n_), n(n_) {
	matrix = VV(n, Row(n, 0));
	for (int i = 0; i < n; ++i)
		set(i, i, 1);
}
Matrix::Matrix(const Row &row) : m(1), n(row.size()), matrix(VV(1, row)) {
	//size???m???vector<Elem>??????mx1???????????????
	(*this) = transport();
}
Matrix::Matrix(int m_, int n_) : m(m_), n(n_) {
	matrix = VV(m, Row(n, 0));
}
Matrix::Matrix(int m_, int n_, Elem e) : m(m_), n(n_) {
	matrix = VV(m, Row(n, e));
}

const Elem Matrix::get(const int i, const int j) const {
	if (0 <= i && i < m && 0 <= j && j < n)
		return matrix[i][j];

	cerr << "get(" << i << "," << j << ")is not exist." << endl;
	throw;
}
void Matrix::set(const int i, const int j, const Elem k) {
	if (0 <= i && i < m && 0 <= j && j < n) {
		*(matrix[i].begin() + j) = k;
		return;
	}
	cerr << "set(" << i << "," << j << ")is not exist." << endl;
	throw;
}

const Matrix Matrix::operator + (const Matrix &rhs) const {
	assert(m == rhs.m && n == rhs.n);

	Matrix tmp(m, n, 0);
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			tmp.set(i, j, get(i, j) + rhs.get(i, j));
		}
	}
	return tmp;
}

const Matrix Matrix::operator * (const Matrix &rhs) const {
	assert(n == rhs.m);

	Matrix tmp(m, rhs.n, 0);
	Elem sum;
	for (int i = 0; i < m; i++)
		for (int j = 0; j < rhs.n; j++) {
			sum = 0;
			for (int k = 0; k < n; k++) {
				sum += get(i, k) * rhs.get(k, j);
			}
			tmp.set(i, j, sum);
		}
	return tmp;
}

const Matrix Matrix::operator - (const Matrix &rhs) const {
	return *this + ((Elem)-1 * rhs);
}

Matrix &Matrix::operator += (const Matrix &rhs) {
	return *this = *this + rhs;
}

Matrix &Matrix::operator *= (const Matrix &rhs) {
	return *this = *this * rhs;;
}

Matrix &Matrix::operator -= (const Matrix &rhs) {
	return *this = *this - rhs;
}

Row &Matrix::operator[](const int x) {
	return matrix[x];
}

const Matrix Matrix::transport() const {
	VV tmp;
	for (int i = 0; i < n; i++) {
		Row row;
		for (int j = 0; j < m; j++)
			row.push_back(get(j, i));
		tmp.push_back(row);
	}
	return tmp;
}

const Matrix Matrix::pow(int x) const {
	Matrix tmp(*this), e(m);
	for (int i = 1; i <= x; i <<= 1) {
		if ((x & i) > 0)
			e = e * tmp;
		tmp = tmp * tmp;
	}
	return e;
}

const Matrix Matrix::cofactor(int x, int y) const {
	VV tmp;
	for (int i = 0; i < m; i++) {
		if (x == i) continue;
		Row row;
		for (int j = 0; j < n; j++) {
			if (y == j) continue;
			row.push_back(get(i, j));
		}
		tmp.push_back(row);
	}
	return Matrix(tmp);
}

const Elem Matrix::det() const {
	assert(n == m);

	if (m == 1)
		return get(0, 0);
	Elem sum = 0;
	for (int i = 0; i < m; i++) {
		sum += ((i % 2 == 0 ? 1 : -1) * get(i, 0)) * Matrix(cofactor(i, 0)).det();
	}
	return sum;
}

const Matrix Matrix::triangulate() const {
	Matrix tmp(*this);
	Elem e;
	int p = 0;
	for (int i = 0; i < m && p < n; i++, p++) {
		if (isZero(tmp.get(i, p))) {
			tmp.set(i, p, 0);
			bool flag = true;
			for (int j = i + 1; j < m; j++)
				if (!isZero(tmp.get(j, p))) {
					for (int k = 0; k < n; k++)
						tmp.set(i, k, tmp.get(i, k) + tmp.get(j, k));
					//tmp[i].swap(tmp[j]);
					flag = false;
					break;
				}
			if (flag) {
				i--;
				continue;
			}
		}
		for (int j = i + 1; j < m; j++) {
			e = tmp.get(j, p) / tmp.get(i, p);
			for (int k = 0; k < n; k++)
				tmp.set(j, k, tmp.get(j, k) - tmp.get(i, k) * e);
		}
	}
	return tmp;
}

const int Matrix::rank() const {
	Matrix tmp(triangulate());
	for (int i = min(tmp.m - 1, tmp.n - 1); i >= 0; i--) {
		for (int j = tmp.n - 1; j >= i; j--)
			if (isZero(tmp.get(i, j)))
				continue;
			else
				return i + 1;
	}
	return 0;
}

const Matrix Matrix::pre_inverse() const {
	assert(m == n);

	Matrix tmp(m, n, 0);
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			tmp.set(i, j, ((i + j) % 2 == 0 ? 1 : -1)*cofactor(i, j).det());
	return tmp.transport();
}

/*O(n!)????£?
const Matrix Matrix::inverse() const {
Matrix tmp(pre_inverse());
Elem e = det();
assert(!isZero(e));
tmp = 1 / e * tmp;
return tmp.transport();
}*/

const Matrix Matrix::inverse() const {
	assert(m == n);

	Matrix tmp(m, n * 2), tmp2(m, n);
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			tmp.set(i, j, get(i, j));
	for (int i = 0; i < m; i++)
		tmp.set(i, i + n, 1);

	tmp = tmp.rowReduction();

	//?????????????????¨??????????????????????????§??????
	for (int i = 0; i < m; i++)
		assert(isZero(tmp.get(i, i) - 1));

	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			tmp2.set(i, j, tmp.get(i, j + n));

	return tmp2;
}

/*
a b c j
d e f k
g h i l

ax+by+cz=j;
dx+ey+fz=k;
gx+hy+iz=l;

|
V

1 0 0 x
0 1 0 y
0 0 1 z
???????????????
*/
const Matrix Matrix::rowReduction() const {
	Matrix tmp(*this);
	Elem e;
	int p = 0;
	for (int i = 0; i < m && p < n; i++, p++) {
		if (isZero(tmp.get(i, p))) {
			tmp.set(i, p, 0);
			bool flag = true;
			for (int j = i + 1; j < m; j++)
				if (!isZero(tmp.get(j, p))) {
					for (int k = 0; k < n; k++)
						tmp.set(i, k, tmp.get(i, k) + tmp.get(j, k));
					//tmp[i].swap(tmp[j]);
					flag = false;
					break;
				}
			if (flag) {
				i--;
				continue;
			}
		}
		e = 1 / tmp.get(i, p);
		tmp.set(i, p, 1);
		for (int k = i + 1; k < n; k++)
			tmp.set(i, k, tmp.get(i, k)*e);
		for (int j = 0; j < m; j++) {
			if (i == j) continue;
			e = tmp.get(j, p);
			for (int k = 0; k < n; k++)
				tmp.set(j, k, tmp.get(j, k) - tmp.get(i, k) * e);
		}
	}
	return tmp;
}

int main() {
	int N, M; cin >> N >> M;
	vector<vector<ld>>edges(N, vector<ld>(M));
	for (int i = 0; i < M; ++i) {
		int a, b; cin >> a >> b; a--; b--;
		edges[a][i]++;
		edges[b][i]--;
	}
	Matrix mat(edges);
	int num=mat.rank();
	int ans = M - num;
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 4220
memory_kb: 73400
final_rank: 10

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;
const ld eps = 1e-9;

// < "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\a.txt" > "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\b.txt"

/* verified AOJ1327 One-Dimensional Cellular Automaton
~Matrix~
??????????°????????¨?????????§??????
vector iostream cmath cassert ??????
Matrix a(VV), b(VV);
?????????:a*b
????????????:l*a
???:a+b
???:a-b
??¢???:a.transport()
?????????:a.cofactor()
?????????:a.det()
a???i???j??????:a.get(i,j)???
a???i??????j?????????k?????£??\:set(i,j,k)
????????????a[i][j] (a[i][j]=k)
a???x???:a.pow(x)
n*n?????¬??????E:Matrix(n)
m*n 0??????:Matrix(m,n)
m*n ??¨????´????p?????????:Matrix(m,n,p)
Row???row??§????????????(m*1??????):Matrix(row)
**(??´??°??????)**
????§????:a.triangulate()
?????????:a.rank()
?????????:a.inverse()
//(????????????a.det()?????????a.pre_inverse()??§?±??????? ??´??°???)
??¬??????????¶???????:a.rowReduction()
//??£???????¬?????¨????????§£??????
***
*/

#include <vector>
#include <iostream>
#include <cmath>
#include <cassert>
using namespace std;

typedef int Elem;
typedef vector<Elem> Row;
typedef vector<Row> VV;

typedef long double ld;
const ld EPS = 1e-11;

const bool isZero(const Elem e) {
	return abs(e) < EPS;
}

struct Matrix {
	VV matrix;
	int n, m;

	Matrix(const VV &matrix_);
	explicit Matrix(int n_);
	explicit Matrix(const Row &row);
	Matrix(int m_, int n_);
	Matrix(int m_, int n_, Elem e);

	const Elem get(const int i, const int j) const;
	void set(const int x, const int y, const Elem k);

	const Matrix operator + (const Matrix &rhs) const;
	const Matrix operator * (const Matrix &rhs) const;
	const Matrix operator - (const Matrix &rhs) const;
	Matrix &operator += (const Matrix &rhs);
	Matrix &operator *= (const Matrix &rhs);
	Matrix &operator -= (const Matrix &rhs);

	Row &operator[](const int x);

	const Matrix transport() const;
	const Matrix pow(int x) const;
	const Matrix cofactor(int x, int y) const;
	const Elem det() const;

	const Matrix triangulate() const;
	const int rank() const;

	//?????????????????¨????????°???(?????????)*(?????????)?????????
	//A:matrix,return det A * A^-1
	const Matrix pre_inverse() const;
	const Matrix inverse() const;
	const Matrix rowReduction() const;
};

const Matrix operator * (const Elem lambda, const Matrix &rhs) {
	Matrix tmp(rhs);
	for (int i = 0; i < rhs.m; i++)
		for (int j = 0; j < rhs.n; j++)
			tmp.set(i, j, tmp.get(i, j) * lambda);
	return tmp;
}

Matrix::Matrix(const VV &matrix_) : matrix(matrix_) {
	m = matrix_.size();
	if (m == 0) n = 0;
	else n = matrix_[0].size();
}
Matrix::Matrix(int n_) : m(n_), n(n_) {
	matrix = VV(n, Row(n, 0));
	for (int i = 0; i < n; ++i)
		set(i, i, 1);
}
Matrix::Matrix(const Row &row) : m(1), n(row.size()), matrix(VV(1, row)) {
	//size???m???vector<Elem>??????mx1???????????????
	(*this) = transport();
}
Matrix::Matrix(int m_, int n_) : m(m_), n(n_) {
	matrix = VV(m, Row(n, 0));
}
Matrix::Matrix(int m_, int n_, Elem e) : m(m_), n(n_) {
	matrix = VV(m, Row(n, e));
}

const Elem Matrix::get(const int i, const int j) const {
	if (0 <= i && i < m && 0 <= j && j < n)
		return matrix[i][j];

	cerr << "get(" << i << "," << j << ")is not exist." << endl;
	throw;
}
void Matrix::set(const int i, const int j, const Elem k) {
	if (0 <= i && i < m && 0 <= j && j < n) {
		*(matrix[i].begin() + j) = k;
		return;
	}
	cerr << "set(" << i << "," << j << ")is not exist." << endl;
	throw;
}

const Matrix Matrix::operator + (const Matrix &rhs) const {
	assert(m == rhs.m && n == rhs.n);

	Matrix tmp(m, n, 0);
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			tmp.set(i, j, get(i, j) + rhs.get(i, j));
		}
	}
	return tmp;
}

const Matrix Matrix::operator * (const Matrix &rhs) const {
	assert(n == rhs.m);

	Matrix tmp(m, rhs.n, 0);
	Elem sum;
	for (int i = 0; i < m; i++)
		for (int j = 0; j < rhs.n; j++) {
			sum = 0;
			for (int k = 0; k < n; k++) {
				sum += get(i, k) * rhs.get(k, j);
			}
			tmp.set(i, j, sum);
		}
	return tmp;
}

const Matrix Matrix::operator - (const Matrix &rhs) const {
	return *this + ((Elem)-1 * rhs);
}

Matrix &Matrix::operator += (const Matrix &rhs) {
	return *this = *this + rhs;
}

Matrix &Matrix::operator *= (const Matrix &rhs) {
	return *this = *this * rhs;;
}

Matrix &Matrix::operator -= (const Matrix &rhs) {
	return *this = *this - rhs;
}

Row &Matrix::operator[](const int x) {
	return matrix[x];
}

const Matrix Matrix::transport() const {
	VV tmp;
	for (int i = 0; i < n; i++) {
		Row row;
		for (int j = 0; j < m; j++)
			row.push_back(get(j, i));
		tmp.push_back(row);
	}
	return tmp;
}

const Matrix Matrix::pow(int x) const {
	Matrix tmp(*this), e(m);
	for (int i = 1; i <= x; i <<= 1) {
		if ((x & i) > 0)
			e = e * tmp;
		tmp = tmp * tmp;
	}
	return e;
}

const Matrix Matrix::cofactor(int x, int y) const {
	VV tmp;
	for (int i = 0; i < m; i++) {
		if (x == i) continue;
		Row row;
		for (int j = 0; j < n; j++) {
			if (y == j) continue;
			row.push_back(get(i, j));
		}
		tmp.push_back(row);
	}
	return Matrix(tmp);
}

const Elem Matrix::det() const {
	assert(n == m);

	if (m == 1)
		return get(0, 0);
	Elem sum = 0;
	for (int i = 0; i < m; i++) {
		sum += ((i % 2 == 0 ? 1 : -1) * get(i, 0)) * Matrix(cofactor(i, 0)).det();
	}
	return sum;
}

const Matrix Matrix::triangulate() const {
	Matrix tmp(*this);
	Elem e;
	int p = 0;
	for (int i = 0; i < m && p < n; i++, p++) {
		if (isZero(tmp.get(i, p))) {
			tmp.set(i, p, 0);
			bool flag = true;
			for (int j = i + 1; j < m; j++)
				if (!isZero(tmp.get(j, p))) {
					for (int k = 0; k < n; k++)
						tmp.set(i, k, tmp.get(i, k) + tmp.get(j, k));
					//tmp[i].swap(tmp[j]);
					flag = false;
					break;
				}
			if (flag) {
				i--;
				continue;
			}
		}
		for (int j = i + 1; j < m; j++) {
			e = tmp.get(j, p) / tmp.get(i, p);
			for (int k = 0; k < n; k++)
				tmp.set(j, k, tmp.get(j, k) - tmp.get(i, k) * e);
		}
	}
	return tmp;
}

const int Matrix::rank() const {
	Matrix tmp(triangulate());
	for (int i = min(tmp.m - 1, tmp.n - 1); i >= 0; i--) {
		for (int j = tmp.n - 1; j >= i; j--)
			if (isZero(tmp.get(i, j)))
				continue;
			else
				return i + 1;
	}
	return 0;
}

const Matrix Matrix::pre_inverse() const {
	assert(m == n);

	Matrix tmp(m, n, 0);
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			tmp.set(i, j, ((i + j) % 2 == 0 ? 1 : -1)*cofactor(i, j).det());
	return tmp.transport();
}

/*O(n!)????£?
const Matrix Matrix::inverse() const {
Matrix tmp(pre_inverse());
Elem e = det();
assert(!isZero(e));
tmp = 1 / e * tmp;
return tmp.transport();
}*/

const Matrix Matrix::inverse() const {
	assert(m == n);

	Matrix tmp(m, n * 2), tmp2(m, n);
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			tmp.set(i, j, get(i, j));
	for (int i = 0; i < m; i++)
		tmp.set(i, i + n, 1);

	tmp = tmp.rowReduction();

	//?????????????????¨??????????????????????????§??????
	for (int i = 0; i < m; i++)
		assert(isZero(tmp.get(i, i) - 1));

	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			tmp2.set(i, j, tmp.get(i, j + n));

	return tmp2;
}

/*
a b c j
d e f k
g h i l

ax+by+cz=j;
dx+ey+fz=k;
gx+hy+iz=l;

|
V

1 0 0 x
0 1 0 y
0 0 1 z
???????????????
*/
const Matrix Matrix::rowReduction() const {
	Matrix tmp(*this);
	Elem e;
	int p = 0;
	for (int i = 0; i < m && p < n; i++, p++) {
		if (isZero(tmp.get(i, p))) {
			tmp.set(i, p, 0);
			bool flag = true;
			for (int j = i + 1; j < m; j++)
				if (!isZero(tmp.get(j, p))) {
					for (int k = 0; k < n; k++)
						tmp.set(i, k, tmp.get(i, k) + tmp.get(j, k));
					//tmp[i].swap(tmp[j]);
					flag = false;
					break;
				}
			if (flag) {
				i--;
				continue;
			}
		}
		e = 1 / tmp.get(i, p);
		tmp.set(i, p, 1);
		for (int k = i + 1; k < n; k++)
			tmp.set(i, k, tmp.get(i, k)*e);
		for (int j = 0; j < m; j++) {
			if (i == j) continue;
			e = tmp.get(j, p);
			for (int k = 0; k < n; k++)
				tmp.set(j, k, tmp.get(j, k) - tmp.get(i, k) * e);
		}
	}
	return tmp;
}

int main() {
	int N, M; cin >> N >> M;
	vector<vector<int>>edges(N, vector<int>(M));
	for (int i = 0; i < M; ++i) {
		int a, b; cin >> a >> b; a--; b--;
		edges[a][i]++;
		edges[b][i]--;
	}
	Matrix mat(edges);
	int num=mat.rank();
	int ans = M - num;
	cout << ans << endl;
	return 0;
}
accuracy: 0.3953488372093023
time_ms: 1060
memory_kb: 12496
final_rank: 12

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;
const ld eps = 1e-9;

// < "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\a.txt" > "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\b.txt"

/* verified AOJ1327 One-Dimensional Cellular Automaton
~Matrix~
??????????°????????¨?????????§??????
vector iostream cmath cassert ??????
Matrix a(VV), b(VV);
?????????:a*b
????????????:l*a
???:a+b
???:a-b
??¢???:a.transport()
?????????:a.cofactor()
?????????:a.det()
a???i???j??????:a.get(i,j)???
a???i??????j?????????k?????£??\:set(i,j,k)
????????????a[i][j] (a[i][j]=k)
a???x???:a.pow(x)
n*n?????¬??????E:Matrix(n)
m*n 0??????:Matrix(m,n)
m*n ??¨????´????p?????????:Matrix(m,n,p)
Row???row??§????????????(m*1??????):Matrix(row)
**(??´??°??????)**
????§????:a.triangulate()
?????????:a.rank()
?????????:a.inverse()
//(????????????a.det()?????????a.pre_inverse()??§?±??????? ??´??°???)
??¬??????????¶???????:a.rowReduction()
//??£???????¬?????¨????????§£??????
***
*/

#include <vector>
#include <iostream>
#include <cmath>
#include <cassert>
using namespace std;

typedef int Elem;
typedef vector<Elem> Row;
typedef vector<Row> VV;

typedef long double ld;
const ld EPS = 1e-11;

const bool isZero(const Elem e) {
	return abs(e) < EPS;
}

struct Matrix {
	VV matrix;
	int n, m;

	Matrix(const VV &matrix_);
	explicit Matrix(int n_);
	explicit Matrix(const Row &row);
	Matrix(int m_, int n_);
	Matrix(int m_, int n_, Elem e);

	const Elem get(const int i, const int j) const;
	void set(const int x, const int y, const Elem k);

	const Matrix operator + (const Matrix &rhs) const;
	const Matrix operator * (const Matrix &rhs) const;
	const Matrix operator - (const Matrix &rhs) const;
	Matrix &operator += (const Matrix &rhs);
	Matrix &operator *= (const Matrix &rhs);
	Matrix &operator -= (const Matrix &rhs);

	Row &operator[](const int x);

	const Matrix transport() const;
	const Matrix pow(int x) const;
	const Matrix cofactor(int x, int y) const;
	const Elem det() const;

	const Matrix triangulate() const;
	const int rank() const;

	//?????????????????¨????????°???(?????????)*(?????????)?????????
	//A:matrix,return det A * A^-1
	const Matrix pre_inverse() const;
	const Matrix inverse() const;
	const Matrix rowReduction() const;
};

const Matrix operator * (const Elem lambda, const Matrix &rhs) {
	Matrix tmp(rhs);
	for (int i = 0; i < rhs.m; i++)
		for (int j = 0; j < rhs.n; j++)
			tmp.set(i, j, tmp.get(i, j) * lambda);
	return tmp;
}

Matrix::Matrix(const VV &matrix_) : matrix(matrix_) {
	m = matrix_.size();
	if (m == 0) n = 0;
	else n = matrix_[0].size();
}
Matrix::Matrix(int n_) : m(n_), n(n_) {
	matrix = VV(n, Row(n, 0));
	for (int i = 0; i < n; ++i)
		set(i, i, 1);
}
Matrix::Matrix(const Row &row) : m(1), n(row.size()), matrix(VV(1, row)) {
	//size???m???vector<Elem>??????mx1???????????????
	(*this) = transport();
}
Matrix::Matrix(int m_, int n_) : m(m_), n(n_) {
	matrix = VV(m, Row(n, 0));
}
Matrix::Matrix(int m_, int n_, Elem e) : m(m_), n(n_) {
	matrix = VV(m, Row(n, e));
}

const Elem Matrix::get(const int i, const int j) const {
	if (0 <= i && i < m && 0 <= j && j < n)
		return matrix[i][j];

	cerr << "get(" << i << "," << j << ")is not exist." << endl;
	throw;
}
void Matrix::set(const int i, const int j, const Elem k) {
	if (0 <= i && i < m && 0 <= j && j < n) {
		*(matrix[i].begin() + j) = k;
		return;
	}
	cerr << "set(" << i << "," << j << ")is not exist." << endl;
	throw;
}

const Matrix Matrix::operator + (const Matrix &rhs) const {
	assert(m == rhs.m && n == rhs.n);

	Matrix tmp(m, n, 0);
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			tmp.set(i, j, get(i, j) + rhs.get(i, j));
		}
	}
	return tmp;
}

const Matrix Matrix::operator * (const Matrix &rhs) const {
	assert(n == rhs.m);

	Matrix tmp(m, rhs.n, 0);
	Elem sum;
	for (int i = 0; i < m; i++)
		for (int j = 0; j < rhs.n; j++) {
			sum = 0;
			for (int k = 0; k < n; k++) {
				sum += get(i, k) * rhs.get(k, j);
			}
			tmp.set(i, j, sum);
		}
	return tmp;
}

const Matrix Matrix::operator - (const Matrix &rhs) const {
	return *this + ((Elem)-1 * rhs);
}

Matrix &Matrix::operator += (const Matrix &rhs) {
	return *this = *this + rhs;
}

Matrix &Matrix::operator *= (const Matrix &rhs) {
	return *this = *this * rhs;;
}

Matrix &Matrix::operator -= (const Matrix &rhs) {
	return *this = *this - rhs;
}

Row &Matrix::operator[](const int x) {
	return matrix[x];
}

const Matrix Matrix::transport() const {
	VV tmp;
	for (int i = 0; i < n; i++) {
		Row row;
		for (int j = 0; j < m; j++)
			row.push_back(get(j, i));
		tmp.push_back(row);
	}
	return tmp;
}

const Matrix Matrix::pow(int x) const {
	Matrix tmp(*this), e(m);
	for (int i = 1; i <= x; i <<= 1) {
		if ((x & i) > 0)
			e = e * tmp;
		tmp = tmp * tmp;
	}
	return e;
}

const Matrix Matrix::cofactor(int x, int y) const {
	VV tmp;
	for (int i = 0; i < m; i++) {
		if (x == i) continue;
		Row row;
		for (int j = 0; j < n; j++) {
			if (y == j) continue;
			row.push_back(get(i, j));
		}
		tmp.push_back(row);
	}
	return Matrix(tmp);
}

const Elem Matrix::det() const {
	assert(n == m);

	if (m == 1)
		return get(0, 0);
	Elem sum = 0;
	for (int i = 0; i < m; i++) {
		sum += ((i % 2 == 0 ? 1 : -1) * get(i, 0)) * Matrix(cofactor(i, 0)).det();
	}
	return sum;
}

const Matrix Matrix::triangulate() const {
	Matrix tmp(*this);
	Elem e;
	int p = 0;
	for (int i = 0; i < m && p < n; i++, p++) {
		if (isZero(tmp.get(i, p))) {
			tmp.set(i, p, 0);
			bool flag = true;
			for (int j = i + 1; j < m; j++)
				if (!isZero(tmp.get(j, p))) {
					for (int k = 0; k < n; k++)
						tmp.set(i, k, tmp.get(i, k) + tmp.get(j, k));
					//tmp[i].swap(tmp[j]);
					flag = false;
					break;
				}
			if (flag) {
				i--;
				continue;
			}
		}
		for (int j = i + 1; j < m; j++) {
			e = tmp.get(j, p) / tmp.get(i, p);
			for (int k = 0; k < n; k++)
				tmp.set(j, k, tmp.get(j, k) - tmp.get(i, k) * e);
		}
	}
	return tmp;
}

const int Matrix::rank() const {
	Matrix tmp(triangulate());
	for (int i = min(tmp.m - 1, tmp.n - 1); i >= 0; i--) {
		for (int j = tmp.n - 1; j >= i; j--)
			if (isZero(tmp.get(i, j)))
				continue;
			else
				return i + 1;
	}
	return 0;
}

const Matrix Matrix::pre_inverse() const {
	assert(m == n);

	Matrix tmp(m, n, 0);
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			tmp.set(i, j, ((i + j) % 2 == 0 ? 1 : -1)*cofactor(i, j).det());
	return tmp.transport();
}

/*O(n!)????£?
const Matrix Matrix::inverse() const {
Matrix tmp(pre_inverse());
Elem e = det();
assert(!isZero(e));
tmp = 1 / e * tmp;
return tmp.transport();
}*/

const Matrix Matrix::inverse() const {
	assert(m == n);

	Matrix tmp(m, n * 2), tmp2(m, n);
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			tmp.set(i, j, get(i, j));
	for (int i = 0; i < m; i++)
		tmp.set(i, i + n, 1);

	tmp = tmp.rowReduction();

	//?????????????????¨??????????????????????????§??????
	for (int i = 0; i < m; i++)
		assert(isZero(tmp.get(i, i) - 1));

	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			tmp2.set(i, j, tmp.get(i, j + n));

	return tmp2;
}

/*
a b c j
d e f k
g h i l

ax+by+cz=j;
dx+ey+fz=k;
gx+hy+iz=l;

|
V

1 0 0 x
0 1 0 y
0 0 1 z
???????????????
*/
const Matrix Matrix::rowReduction() const {
	Matrix tmp(*this);
	Elem e;
	int p = 0;
	for (int i = 0; i < m && p < n; i++, p++) {
		if (isZero(tmp.get(i, p))) {
			tmp.set(i, p, 0);
			bool flag = true;
			for (int j = i + 1; j < m; j++)
				if (!isZero(tmp.get(j, p))) {
					for (int k = 0; k < n; k++)
						tmp.set(i, k, tmp.get(i, k) + tmp.get(j, k));
					//tmp[i].swap(tmp[j]);
					flag = false;
					break;
				}
			if (flag) {
				i--;
				continue;
			}
		}
		e = 1 / tmp.get(i, p);
		tmp.set(i, p, 1);
		for (int k = i + 1; k < n; k++)
			tmp.set(i, k, tmp.get(i, k)*e);
		for (int j = 0; j < m; j++) {
			if (i == j) continue;
			e = tmp.get(j, p);
			for (int k = 0; k < n; k++)
				tmp.set(j, k, tmp.get(j, k) - tmp.get(i, k) * e);
		}
	}
	return tmp;
}

int main() {
	int N, M; cin >> N >> M;
	vector<vector<int>>edges(M, vector<int>(N));
	for (int i = 0; i < M; ++i) {
		int a, b; cin >> a >> b; a--; b--;
		edges[i][a]++;
		edges[i][b]--;
	}
	Matrix mat(edges);
	int num=mat.rank();
	int ans = M - num;
	cout << ans << endl;
	return 0;
}
accuracy: 0.11627906976744186
time_ms: 1770
memory_kb: 12740
final_rank: 15

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

struct edge{
  int to,from;  
  edge(int to,int from) :
    to(to), from(from) {}
  edge(){}
};

int N,M;
bool used[5000];
set<int> G[555];
vector<edge> E;

int main(){
  cin >> N >> M;  
  for(int i=0;i<M;i++){
    int s,t; cin >> s >> t;
    --s; --t;
    E.push_back( edge(t,s) );
    G[s].insert( i );
    G[t].insert( i );
  }
  if( M == 0 ) {
    cout << 0 << endl;
    return 0;
  }
  bool ed = true;
  int res = 0;
  while( ed ){
    int minid=0;
    while( G[minid].empty() ) minid++;
    for(int i=0;i<N;i++){
      if( G[i].empty() ) continue;
      if( G[minid].size() > G[i].size()  ) minid = i;
    }
    //   cout << G[minid].size() << endl;
    res += G[minid].size()-1;
    for(auto it = G[minid].begin(); it != G[minid].end(); it++ ){
      used[*it] = true;
      // cout << "new " << *it << endl;
      for(int i=0;i<N;i++){
        if( i == minid ) continue;
        G[i].erase(*it);
      }
    }
    G[minid].clear();
    ed = false;
    for(int i=0;i<M;i++)
      if( !used[i] ) ed = true;
  }
  cout << res << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 3420
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define range(i,a,b) for(int i=(a);i<(b);++i)
#define rep(i,n)  range(i,0,n)

const double eps=1e-9;
typedef valarray<double> vec;
typedef valarray<vec> mat;

inline int pivoting(mat &a,int k,int &c){
	int n=a.size(),m=a[0].size(),p=k,ret=0;
	for(;c<m;++c){
		double cmax=abs(a[k][c]);
		range(i,k+1,n){
			if(abs(a[i][c])>cmax){
				p=i,ret=1;
				cmax=abs(a[i][c]);
			}
		}
		if(abs(cmax)>eps) break;
	}
	if(k!=p) swap(a[k],a[p]);
	return ret;
}

int forward(mat &a){
	int n=a.size(),m=a[0].size(),ret=0,c=0;
	rep(i,n-1){
		ret+=pivoting(a,i,c);
		if(abs(a[i][c])<eps) break;
		range(j,i+1,n){
			double coef=a[j][c]/a[i][c];
			range(k,c,m) a[j][k]-=coef*a[i][k];
		}
	}
	return ret;
}

int rnk(mat &a){
	int n=a.size(),m=a[0].size(),ret=0;
	rep(i,n)rep(j,m) if(abs(a[i][j])>eps) ret=i+1;
	return ret;
}

int main(void){
	int n,m;
	cin >> n >> m;
	mat a(vec(0.0,m),n);
	rep(i,m){
		int s,t;
		cin >> s >> t;
		s--,t--;
		a[s][i]+=1.0;
		a[t][i]-=1.0;
	}
	forward(a);
	int ans=m-rnk(a);
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 12876
final_rank: 2

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

struct edge{
  int to,from,no,flag;
};
int N,M;
vector<int> same[3111];
vector<int> Gs[511],Gn[511];
edge E[3111];
struct uni{
  int d[3111];
  void init(){ memset(d,-1,sizeof(d)); }
  int find(int a){ return d[a]<0?a:(d[a] = find(d[a])); }
  void marge(int a,int b){
    a = find(a), b = find(b);
    if( a == b ) return;
    if( d[a] > d[b] ) swap(a,b);
    d[a] += d[b]; d[b] = a;   
  }
};
uni U;

void view(){
  cout << "view" << endl;
  for(int i=0;i<M;i++){
    cout << E[i].flag << endl;
  }
}

bool check(){
  //  view();
  for(int i=0;i<M;i++) if( !E[i].flag ) return false;
  return true;
}

bool update(){
  //  view();
  bool ret = false;
  for(int i=0;i<M;i++){
    if( E[i].flag ) {
      int p = U.find(i);
      if( same[p].empty() ) continue;
      
      for(int i=0;i<(int)same[p].size();i++)
	E[same[p][i]].flag = 1;
      ret = true;
      same[p].clear();
    }
  }
  for(int i=0;i<N;i++){
    vector<int> e;
    for(int j=0;j<(int)Gs[i].size();j++)
      if( !E[Gs[i][j]].flag ) e.push_back( Gs[i][j] );
    for(int j=0;j<(int)Gn[i].size();j++)
      if( !E[Gn[i][j]].flag ) e.push_back( Gn[i][j] );
    if(e.size()==1) {
      E[e[0]].flag = 1;      
      ret = true;
    }
 
  }
  return ret;
}

int main(){
  
  cin >> N >> M;
  for(int i=0;i<M;i++){
    int s,t; cin >> s>> t;
    E[i] = (edge){s,t,i,0};
    Gs[s].push_back(i);
    Gn[t].push_back(i);
  }

  U.init();
  for(int i=0;i<N;i++)
    if( Gs[i].size() == 1 && Gn[i].size() ==1 )
      U.marge(Gs[i][0],Gn[i][0]);
  for(int i=0;i<M;i++)
    same[U.find(E[i].no)].push_back( E[i].no );
  
 

  int cnt = 0;
  do{
    if( M == 0 ) continue;
    cnt++;
    for(int i=0;i<M;i++){
      if( E[i].flag ) continue;
      E[i].flag = 1;
      break;
    }
    while( update() );
    
  } while( !check() );
  cout << cnt << endl;
}
accuracy: 0.11627906976744186
time_ms: 200
memory_kb: 1448
final_rank: 14

code_snippet: #include<stdio.h>
#include<algorithm>
using namespace std;
int p[3100];
int q[3100];
double A[510][3100];
double ABS(double a){return max(a,-a);}
double EPS=1e-9;
int main(){
	int a,b;
	scanf("%d%d",&a,&b);
	for(int i=0;i<b;i++){
		scanf("%d%d",p+i,q+i);
		p[i]--;q[i]--;
		A[p[i]][i]+=1.0;
		A[q[i]][i]-=1.0;
	}
	int rank=b;
	int col=0;
	/*for(int i=0;i<a;i++){
		for(int j=0;j<b;j++)printf("%.0f ",A[i][j]);
		printf("\n");
	}*/
	for(int i=0;i<a;i++){
		int at=-1;
		while(col<b){
			for(int j=i;j<a;j++){
				if(ABS(A[j][col])>EPS){
					at=j;break;
				}
			}
			if(~at)break;
			col++;
		}
		if(col>=b)break;
		rank--;
		for(int j=0;j<b;j++)swap(A[i][j],A[at][j]);
		double ks=A[i][col];
		for(int j=0;j<b;j++)A[i][j]/=ks;
		for(int j=i+1;j<a;j++){
			double t=A[j][col];
			for(int k=0;k<b;k++)A[j][k]-=t*A[i][k];
		}
		col++;
		/*for(int k=0;k<a;k++){
			for(int j=0;j<b;j++)printf("%.0f ",A[k][j]);
			printf("\n");
		}*/
	}
	printf("%d\n",rank);
}
accuracy: 1
time_ms: 260
memory_kb: 13324
final_rank: 3

code_snippet: #include <bits/stdc++.h>

#ifdef LOCAL
#include "dump.hpp"
#else
#define dump(...)
#endif

using namespace std;

#define REP(i, a, b) for(int i = (a); i < int(b); ++i)
#define rep(i, n) REP(i, 0, n)
#define ALL(x) begin(x), end(x)

template<class T> inline void chmax(T &a, const T &b) { if(a < b) a = b; }
template<class T> inline void chmin(T &a, const T &b) { if(a > b) a = b; }

typedef double R;
constexpr R EPS = 1e-8;

typedef vector<R> vec;
typedef vector<vec> mat;

int rank_of(const mat& A) {
	const int n = A.size();
	const int m = A[0].size();

	mat B(A);
	int res = 0;
	int col = -1;

	for(int i = 0; i < n; ++i) {
		int pivot = -1;
		for(;;) {
			if(++col == m) goto rank_end;

			for(int j = i; j < n; ++j) {
				if(abs(B[j][col]) > EPS) {
					pivot = j;
					break;
				}
			}
			if(pivot != -1) break;
		}

		B[i].swap(B[pivot]);
		++res;

		for(int j = col + 1; j < m; ++j) {
			B[i][j] /= B[i][col];
		}

		for(int j = i + 1; j < n; ++j) {
			if(abs(B[j][col]) > EPS) {
				for(int k = col + 1; k < m; ++k) {
					B[j][k] -= B[j][col] * B[i][k];
				}
			}
		}
	}

rank_end:;
	return res;
}

int rank_of(const mat& A, const vec& b) {
	const int n = A.size();

	mat B(A);
	for(int i = 0; i < n; ++i) {
		B[i].emplace_back(b[i]);
	}
	return rank_of(B);
}

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	int n, m;
	cin >> n >> m;

	mat A(n, vec(m, 0));

	for(int i = 0; i < m; ++i) {
		int s, t;
		cin >> s >> t;
		A[s - 1][i] = 1;
		A[t - 1][i] = -1;
	}

	cout << m - rank_of(A) << endl;

	return EXIT_SUCCESS;
}
accuracy: 1
time_ms: 20
memory_kb: 24492
final_rank: 4

code_snippet: #include <bits/stdc++.h>
#define REP(i,n) for(int i=0; i<(int)(n); ++i)

using namespace std;

typedef vector<double> Vect;
typedef vector<Vect> Matrix;
const double EPS = 1e-8;

int rank_of_matrix(Matrix M){
    int H = M.size();
    int W = M[0].size();
    int cy, cx;
    for(cy = 0, cx = 0; cy < H && cx < W; cy++, cx++){
        for(int y = cy + 1; y < H; y++){
            if(abs(M[cy][cx]) < abs(M[y][cx])){
                swap(M[cy], M[y]);
            }
        }
        if(abs(M[cy][cx]) < EPS){
            cy--;
            continue;
        }
        for(int y = cy + 1; y < H; y++){
            double p = M[y][cx] / M[cy][cx];
            for(int x = cx; x < W; x++){
                M[y][x] -= p * M[cy][x];
            }
        }
    }
    return cy;
}

int main(){
    int N, M;
    while(cin >> N >> M){
        Matrix Mat(N, Vect(M));
        for(int i = 0; i < M; i++){
            int s, t;
            cin >> s >> t;
            s--; t--;
            Mat[s][i] += 1.0;
            Mat[t][i] -= 1.0;
        }
        cout << M - rank_of_matrix(Mat) << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 320
memory_kb: 24492
final_rank: 5