单向并查集,问至少给几个点可以遍历全图,连通块数量n,入度为0的点的数量m,取max(n,m)~
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1e6+14; int father[maxn],isRoot[maxn],T,M,N,u,v,visit[maxn]; void init () { for (int i=0;i<maxn;i++) father[i]=i; fill (isRoot,isRoot+maxn,0); fill (visit,visit+maxn,0); } int findfather (int x) { int a=x; while (x!=father[x]) x=father[x]; while (a!=father[a]) { int z=a; a=father[a]; father[z]=x; } return x; } void Union (int a,int b) { int faA=findfather(a); int faB=findfather(b); if (faA!=faB) father[faA]=faB; } int main () { while (~scanf ("%d",&T)) { while (T--) { init (); scanf ("%d %d",&N,&M); for (int i=0;i<M;i++) { scanf ("%d %d",&u,&v); visit[v]=1; Union (u,v); } for (int i=1;i<=N;i++) isRoot[findfather(i)]++; int ans=0,ans1=0; for (int i=1;i<=N;i++) if (isRoot[i]) ans++; for (int i=1;i<=N;i++) if (!visit[i]) ans1++; printf ("%d ",max(ans,ans1)); } } return 0; }