https://vjudge.net/problem/POJ-1236
思路: 一个DAG上从入度为0的点出发一定可以走遍当前DAG, 所以第一问输出入度为0的点的个数
对于一个DAG, 入度为0的一定是起点, 出度为0的一定是终点. 仔细思考一下, 如果只有一个起点显然应该加一条边, 如果只有一个终点也应该加一条边, 都可以使图变为一个强连通图
我们对起点或终点哪个更大, 我们就应该加对应的边数,同时要特判只有一个SCC的情况
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=105,M=1e4+5; int ver[M],Next[M],head[N],dfn[N],low[N]; int stack[N],ins[N],c[N],in[N],out[N]; int n,tot,num,top,cnt; void add(int x,int y){ ver[++tot]=y,Next[tot]=head[x],head[x]=tot; } void tarjan(int x){ dfn[x]=low[x]=++num; stack[++top]=x,ins[x]=1; for(int i=head[x];i;i=Next[i]) if(!dfn[ver[i]]){ tarjan(ver[i]); low[x]=min(low[x],low[ver[i]]); } else if(ins[ver[i]]) low[x]=min(low[x],dfn[ver[i]]); if(dfn[x]==low[x]){ cnt++; int y; do{ y=stack[top--],ins[y]=0; c[y]=cnt; }while(x!=y); } } int main(){ scanf("%d",&n); for(int x=1;x<=n;x++){ int y; while(~scanf("%d",&y)&&y) add(x,y); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int x=1;x<=n;x++) for(int i=head[x];i;i=Next[i]){ int y=ver[i]; if(c[x]==c[y]) continue; in[c[y]]++,out[c[x]]++; } int p=0,q=0; for(int i=1;i<=cnt;i++){ if(!in[i]) p++; if(!out[i]) q++; } printf("%d\n",p); if(cnt==1) printf("0"); else printf("%d",max(q,p)); return 0; }