lgP2746[USACO5.3]校园网 发表于 2018-04-04 | 分类于 算法 , 图论 , tarjan | 阅读数 次 链接:lgP2746[USACO5.3]校园网 题解 显然分发学校向接受学校连一条边,然后缩点。 子任务A显然就是入度为零的缩点个数 子任务B则是入度为零和出度为零的缩点个数的最大值 有一个坑点,只有一个强连通分量的情况 123456789101112131415161718192021222324252627282930313233343536373839404142434445 #include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #define rep(i,x,y) for(register int i=x;i<=y;++i) #define repd(i,x,y) for(register int i=x;i>=y;--i) #define ll long long using namespace std; const int N=1e5; struct node{ int v,nxt; inline void init(int x,int y){v=x; nxt=y;} }e[N]; int head[N],dfn[N],low[N],cnt,bl[N],du[N][2],n,m,in[N],stck[N],idx,tot,x,ans,res[2]; inline void adde(int x,int y){e[cnt].init(y,head[x]);head[x]=cnt++;} void tarjan(int u){ in[u]=1; stck[++idx]=u; dfn[u]=low[u]=++tot; for(int i=head[u],v;i!=-1;i=e[i].nxt){ if(!dfn[v=e[i].v]){tarjan(v); low[u]=min(low[u],low[v]);} else if(in[v])low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]){ cnt++; do{in[stck[idx]]=0; bl[stck[idx--]]=cnt;}while(u!=stck[idx+1]); } } int main(){ memset(head,-1,sizeof(head)); scanf("%d",&n); rep(i,1,n)while(~scanf("%d",&x)&&x){ adde(i,x); }cnt=0; rep(i,1,n)if(!dfn[i])tarjan(i); rep(u,1,n)for(int i=head[u],v;i!=-1;i=e[i].nxt)if(bl[v=e[i].v]!=bl[u]){ du[bl[u]][0]++; du[bl[v]][1]++; } rep(i,1,cnt){ans+=(du[i][1]==0); res[0]+=(du[i][0]==0);res[1]+=(du[i][1]==0);} printf("%d\n%d",ans,cnt!=1?max(res[0],res[1]):0); return 0;}