5971 打击犯罪
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题目描述 Description
某个地区有n(n<=1000)个犯罪团伙,当地警方按照他们的危险程度由高到低给他们编号为1-n,他们有些团伙之间有直接联系,但是任意两个团伙都可以通过直接或间接的方式联系,这样这里就形成了一个庞大的犯罪集团,犯罪集团的危险程度唯一由集团内的犯罪团伙数量确定,而与单个犯罪团伙的危险程度无关(该犯罪集团的危险程度为n)。现在当地警方希望花尽量少的时间(即打击掉尽量少的团伙),使得庞大的犯罪集团分离成若干个较小的集团,并且他们中最大的一个的危险程度不超过n/2。为达到最好的效果,他们将按顺序打击掉编号1到k的犯罪团伙,请编程求出k的最小值。
输入描述 Input Description
第一行一个正整数n。接下来的n行每行有若干个正整数,第一个整数表示该行除第一个外还有多少个整数,若第i行存在正整数k,表示i,k两个团伙可以直接联系。
输出描述 Output Description
一个正整数,为k的最小值
样例输入 Sample Input
7
2 2 5
3 1 3 4
2 2 4
2 2 3
3 1 6 7
2 5 7
2 5 6
样例输出
Sample Output
1
数据范围及提示
Data Size & Hint
n<=1000
输出1(打击掉红色团伙)
1 #include<iostream> 2 using namespace std; 3 #include<cstdio> 4 #include<cstring> 5 int n,m,a,t,ans; 6 int map[10100][10010]; 7 int group[10010]; 8 int far[10010]; 9 bool b; 10 int find(int a) 11 { 12 return a==far[a]?a:far[a]=find(far[a]); 13 } 14 void In_() 15 { 16 cin>>n; 17 t=n/2; 18 for(int i=1;i<=n;++i) 19 { 20 scanf("%d",&m); 21 for(int j=1;j<=m;++j) 22 { 23 scanf("%d",&a); 24 if(a>i)map[i][++map[i][0]]=a; 25 } 26 } 27 } 28 void Work_() 29 { 30 for(int k=1;k<=n;++k)far[k]=k; 31 for(int i=n;i>=1;--i) 32 { 33 int r=find(i); 34 memset(group,0,sizeof(group)); 35 for(int j=1;j<=map[i][0];++j) 36 { 37 int rr=find(map[i][j]); 38 if(rr!=r)far[rr]=r; 39 } 40 for(int j=1;j<=n;++j) 41 { 42 group[find(j)]++; 43 } 44 for (int j=1;j<=n;++j) 45 if(group[j]>t) 46 { 47 b=1; 48 } 49 if(b==1) 50 { 51 cout<<i;break; 52 } 53 } 54 } 55 int main() 56 { 57 In_(); 58 Work_(); 59 return 0; 60 }