tarjan缩点后,第一问答案显然是入度为零的点得个数
第二问:考虑到 没有入度或出度为0的点 的图强连通,
所以答案就是max{入度为零的个数,出度为零的个数}
(把出度为零的连到入度为零的点,然后剩下为零的随便连一连就可以)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
using namespace std;
const int maxn=,maxm=; LL rd(){
LL x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N;
int eg[maxm][],egh[maxn],ect,bel[maxn];
int dfn[maxn],low[maxn],stk[maxn],tot,pct,sct;
int tin,tout;
bool instk[maxn],in[maxn],out[maxn]; void tarjan(int x){
dfn[x]=low[x]=++tot;stk[++sct]=x;instk[x]=;
for(int i=egh[x];i!=-;i=eg[i][]){
int j=eg[i][];
if(instk[j]) low[x]=min(low[x],dfn[j]);
else if(!dfn[j]){
tarjan(j);low[x]=min(low[x],low[j]);
}
}
if(dfn[x]==low[x]){
pct++;
while(sct){
instk[stk[sct]]=;
bel[stk[sct]]=pct;
if(stk[sct--]==x) break;
}
}
} inline void adeg(int a,int b){
eg[ect][]=b;eg[ect][]=egh[a];egh[a]=ect++;
} int main(){
int i,j,k;
N=rd();memset(egh,-,sizeof(egh));
for(i=;i<=N;i++){
while(j=rd()) adeg(i,j);
}
for(i=;i<=N;i++){
if(!dfn[i]) tarjan(i);
}
for(i=;i<=N;i++){
for(j=egh[i];j!=-;j=eg[j][]){
k=eg[j][];
int ii=bel[i],kk=bel[k];
if(ii!=kk){
in[kk]=;out[ii]=;
}
}
}for(i=;i<=pct;i++){
if(!in[i]) tin++;
if(!out[i]) tout++;
}
if(pct>)printf("%d\n%d",tin,max(tin,tout));
else printf("1\n0"); }