C. Learning Languages 求联通块的个数
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <list> 13 #include <iomanip> 14 #include <cstdlib> 15 #include <sstream> 16 using namespace std; 17 typedef long long LL; 18 const int INF=0x5fffffff; 19 const double EXP=1e-6; 20 const int MS=105; 21 const int mod=9973; 22 23 int lang[MS][MS]; 24 int con[MS][MS]; 25 int flag[MS]; 26 int zero,n,m; 27 28 /* 29 将n个联通块连接起来需要n-1条边。 30 问题转化为求联通块的个数。 注意空集的时候ans==定点个数 31 */ 32 33 int main() 34 { 35 memset(lang,0,sizeof(lang)); 36 memset(con,0,sizeof(con)); 37 memset(con,0,sizeof(con)); 38 zero=0; 39 scanf("%d%d",&n,&m); 40 int cnt,t; 41 for(int i=1;i<=n;i++) 42 { 43 scanf("%d",&cnt); 44 if(cnt>0) 45 zero=1; 46 for(int j=0;j<cnt;j++) 47 { 48 scanf("%d",&t); 49 lang[i][t]=1; 50 } 51 } 52 for(int k=1;k<=m;k++) 53 { 54 for(int i=1;i<=n;i++) 55 for(int j=1;j<=n;j++) 56 if(lang[i][k]&&lang[j][k]) 57 con[i][j]=1; 58 } 59 for(int i=1;i<=n;i++) 60 con[i][i]=1; 61 for(int k=1;k<=n;k++) 62 for(int i=1;i<=n;i++) 63 for(int j=1;j<=n;j++) 64 if(con[i][k]&&con[k][j]) 65 con[i][j]=1; 66 int ans=0; 67 for(int i=1;i<=n;i++) 68 { 69 if(!flag[i]) 70 { 71 ans++; 72 for(int j=1;j<=n;j++) 73 if(con[i][j]) 74 flag[j]=1; 75 } 76 } 77 if(zero) 78 printf("%d\n",ans-zero); 79 else 80 printf("%d\n",ans); 81 return 0; 82 }