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++ (judge verdict: Accepted)

#include<iostream>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;
vector<int> vec[10010],rvec[10010];
bool used[10010];
int cmp[10010]={};
stack<int> st;
void dfs(int a){
    used[a] = true;
    for(int i=0;i<vec[a].size();i++){
        if(used[vec[a][i]]) continue;
        dfs(vec[a][i]);
    }
    st.push(a);
}
void rdfs(int a,int k){
    used[a] = true;
    cmp[a] = k;
    for(int i=0;i<rvec[a].size();i++){
        if(used[rvec[a][i]]) continue;
        rdfs(rvec[a][i],k);
    }
}
int main()
{
    int n,m,s,t;
    cin >> n >> m;
    for(int i=0;i<m;i++){
        cin >> s >> t;
        vec[s].push_back(t);
        rvec[t].push_back(s);
    }
    
    fill(used,used+n,false);
    for(int i=0;i<n;i++){
        if(!used[i]) dfs(i);
    }
    
    fill(used,used+n,false);
    int cnt = 0;
    while(!st.empty()){
        int a = st.top();
        st.pop();
        if(used[a]) continue;
        rdfs(a,cnt);
        cnt++;
    }
    
    int sum1 = cnt,sum2 = cnt;
    
    fill(used,used+n,false);
    for(int i=0;i<n;i++){
        for(int j=0;j<vec[i].size();j++){
            if(!used[cmp[i]] && cmp[i] != cmp[vec[i][j]]){
                used[cmp[i]] = true;
                sum1--;
            }
        }
    }
    
    fill(used,used+n,false);
    for(int i=0;i<n;i++){
        for(int j=0;j<rvec[i].size();j++){
            if(!used[cmp[i]] && cmp[i] != cmp[rvec[i][j]]){
                used[cmp[i]] = true;
                sum2--;
            }
        }
    }
    if(cnt == 1){
        sum1 = 0;
        sum2 = 0;
    }
    cout << max(sum1,sum2) << endl;
    
    return 0;
}