某個地區有n(n<=1000)個犯罪團伙,當地警方按照他們的危險程度由高到低給他們編號爲1-n,他們有些團伙之間有直接聯繫,可是任意兩個團伙均可以經過直接或間接的方式聯繫,這樣這裏就造成了一個龐大的犯罪集團,犯罪集團的危險程度惟一由集團內的犯罪團伙數量肯定,而與單個犯罪團伙的危險程度無關(該犯罪集團的危險程度爲n)。如今當地警方但願花盡可能少的時間(即打擊掉儘可能少的團伙),使得龐大的犯罪集團分離成若干個較小的集團,而且他們中最大的一個的危險程度不超過n/2。爲達到最好的效果,他們將按順序打擊掉編號1到k的犯罪團伙,請編程求出k的最小值。ios
第一行一個正整數n。接下來的n行每行有若干個正整數,第一個整數表示該行除第一個外還有多少個整數,若第i行存在正整數k,表示i,k兩個團伙能夠直接聯繫。編程
一個正整數,爲k的最小值ide
7
2 2 5
3 1 3 4
2 2 4
2 2 3
3 1 6 7
2 5 7
2 5 6
1spa
輸出1(打擊掉紅色團伙)code
1 #include<iostream> 2 using namespace std; 3 const int N = 1010; 4 int f[N], a[N][N], sum[N], n; 5 void init(){ 6 for(int i = 1; i <= n; i++){ 7 f[i] = i; 8 sum[i] = 1; 9 } 10 } 11 int getf(int x){ 12 if(x == f[x]) return x; 13 else return f[x] = getf(f[x]); 14 } 15 int main(){ 16 cin >> n; 17 init(); 18 for(int i = 1; i <= n; i++){ 19 cin >> a[i][0]; 20 for(int j = 1; j <= a[i][0]; j++){ 21 cin >> a[i][j]; 22 } 23 } 24 for(int i = n; i >= 1; i--){ //逆向枚舉 25 for(int j = 1; j <= a[i][0]; j++){ 26 if(a[i][j] > i){ //由於是順序刪除,因此刪除該點時,那麼以前的點已經刪除了 27 int t1 = getf(i), t2 = getf(a[i][j]); 28 if(t1 != t2){ 29 f[t2] = t1; 30 sum[t1] += sum[t2]; 31 if(sum[t1] > (n + 1) / 2){ 32 cout << i << endl; 33 return 0; 34 } 35 } 36 } 37 } 38 } 39 return 0; 40 }