Problem:
Road Improvement

Aizu is a country famous for its rich tourism resources and has N cities, each of which is uniquely identified with a number (0 to N-1). It has a road network consisting of M one-way roads connecting a city to another.

All the roads connecting the cities in Aizu have a row of cherry trees along their routes. For enhancing the cherry-viewing experience, a proposal was made to modify the road network so that a tourist can travel around all the roads. To achieve this target, it was decided to construct several one-way roads, each connecting two cities and abiding by the following rules.

The newly constructed road is for one-way traffic

Starting from any city, a tourist is able to make a roundtrip and return to the city, whereby he/she drives all the roads exhaustively, including the newly constructed ones. Multiple passages of some of the roads are allowed.

You, as a tourism promotion officer, are assigned with the task of writing a program for the road construction project.

Write a program to determine the minimum number of roads to be constructed given the road network information in Aizu.

Input

The input is given in the following format.

N M
s_1 t_1
s_2 t_2
:
s_M t_M

The first line provides the number of cities N (1 ≤ N ≤ 104) and roads M (0 ≤ M ≤ 105). Each of the subsequent M lines provides the numbers assigned to start and destination cities for the i-th road: s_i, t_i (0 ≤ s_i, t_i ≤ N-1) , where s_i ≠ t_i. (no duplicate appearance of a road)

Output

Output the minimum number of roads to be newly constructed.

Sample Input 1

6 7
0 2
2 1
1 0
2 3
4 3
4 5
5 4

Sample Output 1

2

Sample Input 2

6 9
0 2
2 1
1 0
2 3
4 3
4 5
5 4
5 2
3 4

Sample Output 2

0

Solution in C++14 (judge verdict: Accepted)

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

class strongly_connected_component {
    using graph = std::vector<std::vector<int>>;
public:
    strongly_connected_component(int n) : g(n), rg(n), cmp(n), K(0) {}

    void add_edge(int s, int t) {
        g[s].push_back(t);
        rg[t].push_back(s);
    }

    void build() {
        const int n = g.size();
        std::vector<bool> used(n);
        for(int v = 0; v < n; ++v) {
            if(!used[v]) dfs(v, used);
        }
        std::fill(std::begin(used), std::end(used), false);
        int k = 0;
        for(int i = (int)vs.size() - 1; i >= 0; --i) {
            if(!used[vs[i]]) rdfs(vs[i], k++, used);
        }
        K = k;
    }

    int belongs(int v) const {
        return cmp[v];
    }

    graph build_graph() { // also call build()
        build();
        int const V = g.size();
        std::vector<std::set<int>> s(K);
        graph res(K);
        for(int v = 0; v < V; ++v) {
            for(const auto to : g[v]) {
                s[cmp[v]].insert(cmp[to]);
            }
        }
        for(int i = 0; i < K; ++i) { // remove self-loop edge
            for(auto j : s[i]) {
                if(i != j) res[i].push_back(j);
            }
        }
        return res;
    }

private:
    void dfs(int v, std::vector<bool>& used) {
        used[v] = true;
        for(const auto to : g[v]) {
            if(!used[to]) dfs(to, used);
        }
        vs.push_back(v);
    }
    void rdfs(int v, int k, std::vector<bool>& used) {
        used[v] = true;
        cmp[v] = k;
        for(auto to : rg[v]) {
            if(!used[to]) rdfs(to, k, used);
        }
    }

private:
    graph g, rg;
    std::vector<int> cmp, vs;
    int K;
};

int main() {
    int n, m; cin >> n >> m;
    strongly_connected_component scc(n);
    for(int i = 0; i < m; ++i) {
        int s, t; cin >> s >> t;
        scc.add_edge(s, t);
    }
    auto g = scc.build_graph();
    n = g.size();
    if(n == 1) {
        cout << 0 << endl;
        return 0;
    }
    vector<int> in(n), out(n);
    for(int i = 0; i < n; ++i) {
        out[i] = g[i].size();
        for(auto to : g[i]) {
            in[to] += 1;
        }
    }
    int scnt = 0, tcnt = 0;
    for(int i = 0; i < n; ++i) {
        scnt += in[i] == 0;
        tcnt += out[i] == 0;
    }
    cout << max(scnt, tcnt) << endl;
}