【问题描述】
在数学中,我们常常需要完成若干命题的等价性证明。
例如:有4个命题a,b,c,d,要证明他们是等价的,我们需要证明a<=>b,然后b<=>c,最后c<=>d。注意每次证明是双向的,因此一共完成了6次推导。另一种证明方法是:证明a->b,然后b->c,接着c->d,最后d->a,只须4次证明。
现在你任务是证明 n 个命题全部等价,且你的朋友已经为你作出了m次推导(已知每次推导的内容),你至少还需做几次推导才能完成整个证明。
【输入格式】
有T组数据,每组数据第一行为两个整数n和m,即命题数和已完成的推导个数(编号为1..n)。以下m行每行包含两个整数s1和s2(1<=s1,s2<=n,s1!=s2),表明已经证明了s1->s2。
【输出格式】
输出还需要做推导数的最小值。
【输入样例】
2
4 0
3 2
1 2
1 3
【输出样例】
4
2
【数据范围】
T<=100
1<=n<=20 000
0<=m<=50 000
将命题a,b,c,d……作为顶点,由于证明具有单向性,故将已证明过的命题做成一张有向图,然后求出有向图中已有的强连通分量,将每个强连通分量缩成一个代表元(因为同属强连通分量内的命题不需要进行额外的证明(加边)),得到一张新的DAG图,在DAG图中寻找那些出度入度为0的点分别记录个数a,b,max(a,b)就是所求
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>