codevs 5971 打击犯罪 x
题目描述 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(打击掉红色团伙)
分类标签 Tags 点此展开
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define Maxn 10100 5 6 using namespace std; 7 8 int n,t,r1,r2; 9 int f[Maxn],group[Maxn]; 10 int gx[Maxn][Maxn]; 11 bool qwq; 12 13 int find(int x) 14 { 15 return x == f[x] ? x : f[x]=find(f[x]); 16 } 17 18 void In() 19 { 20 int p,k,q=0; 21 scanf("%d",&n); 22 t=n/2; 23 for(int i=1;i<=n;i++)//初始化 24 { 25 f[i]=i; 26 } 27 for(int i=1;i<=n;i++) 28 { 29 cin>>p; 30 q++; 31 while(p>0) 32 { 33 p--; 34 scanf("%d",&k); 35 if(k>q) gx[q][++gx[q][0]]=k;//gx[q][0]进行储存q能够连接到的边数 36 } 37 } 38 39 } 40 41 void QAQ() 42 { 43 for(int i=n;i>=1;--i) 44 { 45 memset(group,0,sizeof(group));//进行清空,便于记录 46 for(int j=1;j<=gx[i][0];++j) 47 { 48 r1=find(i); 49 r2=find(gx[i][j]); 50 if(r2!=r1) f[r2]=r1;//合并 51 } 52 for(int qq=1;qq<=n;qq++) 53 { 54 group[find(qq)]++; 55 } 56 for(int h=1;h<=n;h++) 57 if(group[h]>t) 58 { 59 qwq=1; 60 } 61 if(qwq==1) 62 { 63 printf("%d",i); 64 break; 65 } 66 } 67 } 68 69 int main() 70 { 71 In(); 72 QAQ(); 73 return 0; 74 }