#include using namespace std; const int N = 1e3 + 5; /* 测试用例: 2 4 3 3 4 1 3 2 3 3 3 1 3 1 2 2 3 答案: 2 1 */ int match[N]; int st[N], g[N][N]; int n, m; int dfs(int x) { for (int i = 1; i <= n; i++) { if (g[x][i] && !st[i]) { st[i] = 1; int t = match[i]; if (t == -1 || dfs(t)) { match[i] = x; return 1; } } } return 0; } int main() { int T; cin >> T; // T组测试数据 while (T--) { cin >> n >> m; // n个节点,m条边 // 多组测试数据 memset(match, -1, sizeof match); memset(g, 0, sizeof g); for (int i = 0; i < m; i++) { int a, b; cin >> a >> b; g[a][b] = 1; // a->b,有向图 } // 如果a->b,b->c,则 a->c,题意中说如果存在传递关系,需要我们建立关系清晰的边,也就是, // 用 floyd,在O(N^3)的复杂度下完善点点之间的边关系 for (int k = 1; k <= n; k++) for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) g[i][j] |= g[i][k] & g[k][j]; // 新图建成,开始跑匈牙利算法,求二分图的最大匹配 int cnt = 0; for (int i = 1; i <= n; i++) { memset(st, 0, sizeof st); if (dfs(i)) cnt++; } // 二分图的最小点覆盖 = n- 二分图的最大匹配 printf("%d\n", n - cnt); } return 0; }