codevs 5971 打击犯罪
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 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int f[1005],a[1005][1005],num[1005],b[1005]; 6 int find(int x) 7 { 8 if (f[x]==x) return f[x]; 9 f[x]=find(f[x]); 10 return f[x]; 11 } 12 13 /*int find(int x) 14 { 15 if(f[x]==x)return f[x]=find(f[x]); 16 return f[x]; 17 }*/ 18 int main() 19 { 20 int n,i,j,z,k,saber; 21 bool pd; 22 scanf("%d",&n); 23 for(i=1;i<=n;++i) 24 { 25 scanf("%d",&k); 26 for (j=1;j<=k;++j) 27 { 28 scanf("%d",&z); 29 if(z>i) 30 a[i][++num[i]]=z;//只存大的 31 } 32 } 33 for(k=1;k<=n/2;++k)//危险程度不超过n/2 34 { 35 memset(b,0,sizeof(b)); 36 for(i=1;i<=n;++i) 37 { 38 f[i]=i; 39 } 40 for(i=k+1;i<=n;++i) 41 for(j=1;j<=num[i];++j)//枚举能到达的点(邻接表) 42 { 43 f[find(i)]=find(a[i][j]); 44 } 45 for(i=1;i<=n;++i) 46 { 47 saber=find(i); 48 } 49 for(i=1;i<=n;++i) 50 { 51 b[f[i]]++; 52 } 53 pd=true; 54 for(i=1;i<=n;++i) 55 { 56 if(b[i]>n/2) 57 { 58 pd=false; 59 break; 60 } 61 } 62 if(pd==true) 63 { 64 printf("%d",k); 65 return 0; 66 } 67 } 68 return 0; 69 }