/*
    求最小加边使有向图变为强连通
    先缩点,然后计算各个强连通分量的入度为0的个数,出度为0的个数
    1) SCC=1, 不需添边
    2) 添max( incnt, outcnt )   
                    贪心策略,汇基向点基连边,再添边的连接剩下的点基/汇基即可

*/

#include
<cstdio>
#include
<cstring>
#include
<algorithm>
#include
<vector>
using namespace std;

const int MAXN=20010;

int n,m;
vector
<int>G[2][MAXN];
int ID[MAXN],SCC,flag;
int order[MAXN],cnt;
int in[MAXN],out[MAXN];

void dfs(int u){
    ID[u]
=SCC;
    
for(int i=0;i<G[flag][u].size();i++){
        
int v=G[flag][u][i];
        
if(!ID[v])dfs(v);
    }

    
if(flag)order[++cnt]=u;
}


int main(){
    
int T,a,b;
    scanf(
"%d",&T);
    
while(T--){
        scanf(
"%d%d",&n,&m);
        
for(int i=1;i<=n;i++){
            G[
0][i].clear();
            G[
1][i].clear();
        }

        
while(m--){
            scanf(
"%d%d",&a,&b);
            G[
0][a].push_back(b);
            G[
1][b].push_back(a);
        }

        flag
=SCC=1;
        cnt
=0;
        memset(ID,
0,sizeof(ID));
        
for(int i=1;i<=n;i++)
            
if(!ID[i])dfs(i);
        flag
=SCC=0;
        memset(ID,
0,sizeof(ID));
        
for(int i=cnt;i;i--){//注意是order[i]
            if(ID[order[i]])continue;
            SCC
++;
            dfs(order[i]);
        }

        
if(SCC==1){puts("0");continue;}
        memset(
out,0,sizeof(out));
        memset(
in,0,sizeof(in));
        
for(int i=1;i<=n;i++)
            
for(int j=0;j<G[0][i].size();j++){
                
int v=G[0][i][j];
                
if(ID[i]!=ID[v]){
                    
in[ID[v]]++;
                    
out[ID[i]]++;
                }

            }

        
int incnt=0,outcnt=0;
        
for(int i=1;i<=SCC;i++){
            
if(in[i]==0)incnt++;
            
if(out[i]==0)outcnt++;
        }

        printf(
"%d\n",max(incnt,outcnt));
    }

    
return 0;
}