题目大意:N(2
解题思路:1.先求强连通分支,然后把图缩小成为一个有向无环图;
2.求出这个有向无环图中,入度为0的点的个数为a,出度为0的点的个数为b;
3.第一个问题的答案就是a,第二个问题的答案为max{a,b};
4.最恶心的地方:当一开始这个图就是一个强连通图的时候,第二问题的答案为0。
#include #include #include #include #include #include #include #include #include #include using namespace std ; const int N=200 ; const int M=10010 ; struct node { int u,v,next ; }e1[M] ; struct node1 { int u,v,next; }e2[M] ; int head1[N],head2[N],dfn[N],low[N],belong[N],stack[N],vist[N],in[N],out[N] ; int top1,top2,sum,cnt,dep; void add1(int u , int v) { e1[top1].u=u; e1[top1].v=v; e1[top1].next=head1[u] ; head1[u]=top1++; } void add2(int u , int v) { e2[top2].u=u; e2[top2].v=v; e2[top2].next=head2[u] ; head2[u]=top2++; } void tarjan(int u) { low[u]=dfn[u]=++dep; stack[cnt++]=u; vist[u]=1; for(int i = head1[u] ; i!= -1 ; i=e1[i].next) { int v=e1[i].v ; if(!dfn[v]) { tarjan(v) ; low[u] = min( low[u] , low[v]) ; } else if(vist[v]) low[u] = min( low[u] , dfn[v] ) ; } if(dfn[u] == low[u]) { int x; sum++; do { x = stack[--cnt]; vist[x]=0; belong[x]=sum; }while(x != u) ; } } int main() { int n; while(~scanf("%d",&n)) { memset(head1,-1,sizeof(head1)); memset(head2,-1,sizeof(head2)); memset(belong,0,sizeof(belong)) ; memset(in,0,sizeof(in)); memset(out,0,sizeof(out)) ; top1=top2=0; for(int i = 1 ; i <= n ; i++) { int to ; scanf("%d",&to) ; while(to) { add1(i,to) ; scanf("%d",&to) ; } } memset(vist,0,sizeof(vist)); memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); cnt=dep=sum=0; for(int i = 1 ; i <= n ; i++) if(!dfn[i]) tarjan(i) ; for(int i = 1 ; i <= n ; i++) for(int j = head1[i] ; j!=-1 ; j=e1[j].next) { int v = e1[j].v ; if(belong[i] != belong[v]) { // printf("**"); add2(belong[i],belong[v]) ; } } for(int i = 1 ; i <= sum ; i++) for(int j = head2[i] ; j!=-1 ; j=e2[j].next) { int v = e2[j].v ; in[v]++; out[i]++; } int a=0,b=0; // printf("%d ",sum ); for(int i = 1 ; i <= sum ; i++) { if(in[i] == 0 ) a++ ; if(out[i] == 0 ) b++ ; } if(sum <= 1 ) { printf("1\n"); printf("0\n") ; } else { printf("%d\n",a); printf("%d\n",max(a,b)) ; } } return 0 ; }