这道题和上一道【最受欢迎的牛】差不多,都是强连通分量的练习题;
第一问实际上就是问缩点后入度为0的点有多少,第二问就是问添加几条边能使缩点后的图变成强连通图;
第一问好做,第二问需要动下脑子,也不难;
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<ctime> 5 #include<cstring> 6 #include<string> 7 #include<algorithm> 8 using namespace std; 9 const int maxn=105; 10 int n,x,y,v; 11 struct node{ 12 int y,next; 13 }e[maxn*maxn<<1]; 14 int linkk[maxn],len=0; 15 int pre[maxn],low[maxn],scc_cnt=0,dfs_clock=0,z[maxn],top=0,in[maxn],out[maxn],sccno[maxn]; 16 bool b[maxn][maxn]; 17 void insert(int x,int y){ 18 e[++len].y=y; 19 e[len].next=linkk[x]; 20 linkk[x]=len; 21 } 22 void dfs(int x){ 23 pre[x]=low[x]=++dfs_clock; 24 z[++top]=x; 25 for(int i=linkk[x];i;i=e[i].next){ 26 if(!pre[e[i].y]){ 27 dfs(e[i].y); 28 low[x]=min(low[x],low[e[i].y]); 29 } 30 else if(!sccno[e[i].y])low[x]=min(low[x],pre[e[i].y]); 31 } 32 if(low[x]==pre[x]){ 33 scc_cnt++; 34 while(true){ 35 sccno[z[top]]=scc_cnt; 36 if(z[top]==x){top--;break;} 37 top--; 38 } 39 } 40 } 41 void init(){ 42 scanf("%d",&n); 43 for(int i=1;i<=n;i++){ 44 while(scanf("%d",&x)&&x)insert(i,x); 45 } 46 } 47 void slove(){ 48 for(int i=1;i<=n;i++)if(!pre[i])dfs(i); 49 for(int j=1;j<=n;j++) 50 for(int i=linkk[j];i;i=e[i].next){ 51 x=sccno[j],y=sccno[e[i].y]; 52 if(x==y||b[x][y])continue; 53 b[x][y]=1;in[y]++,out[x]++; 54 } 55 x=0,y=0; 56 for(int i=1;i<=scc_cnt;i++){ 57 if(!in[i])x++; 58 if(!out[i])y++; 59 } 60 printf("%d %d ",x,scc_cnt==1?0:max(x,y)); 61 } 62 int main(){ 63 //freopen("1.in","r",stdin); 64 //freopen("1.out","w",stdout); 65 init(); 66 slove(); 67 }