题目描述
某个地区有n(n<=1000)个犯罪团伙,当地警方按照他们的危险程度由高到低给他们编号为1-n,他们有些团伙之间有直接联系,但是任意两个团伙都可以通过直接或间接的方式联系,这样这里就形成了一个庞大的犯罪集团,犯罪集团的危险程度唯一由集团内的犯罪团伙数量确定,而与单个犯罪团伙的危险程度无关(该犯罪集团的危险程度为n)。现在当地警方希望花尽量少的时间(即打击掉尽量少的团伙),使得庞大的犯罪集团分离成若干个较小的集团,并且他们中最大的一个的危险程度不超过n/2。为达到最好的效果,他们将按顺序打击掉编号1到k的犯罪团伙,请编程求出k的最小值。
输入
第一行一个正整数n。接下来的n行每行有若干个正整数,第一个整数表示该行除第一个外还有多少个整数,若第i行存在正整数k,表示i,k两个团伙可以直接联系。
输出
一个正整数,为k的最小值
样例输入
7
2 2 5
3 1 3 4
2 2 4
2 2 3
3 1 6 7
2 5 7
2 5 6
样例输出
1
提示
输出1(打击掉红色团伙)
#include <bits/stdc++.h>
using namespace std;
const int N=1005;
int n,a[N][N],f[N],pd[N];
int getfa(int x){
if(f[x]==x){
return x;
}else{
return f[x]=getfa(f[x]);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
f[i]=i;
pd[i]=1;
cin>>a[i][0];
for(int j=1;j<=a[i][0];j++){
cin>>a[i][j];
}
}
bool r=false;
for(int j=n;j>=1;j--){
for(int i=1;i<=a[j][0];i++){
if(a[j][i]>=j){
int u=getfa(j),v=getfa(a[j][i]);
if(u!=v){
if(u<v){
f[u]=v;
pd[v]+=pd[u];
if(pd[v]>n/2){
cout<<j;
r=true;
break;
}
}else{
f[v]=u;
pd[u]+=pd[v];
if(pd[u]>n/2){
cout<<j;
r=true;
break;
}
}
}
}
}
if(r)break;
}
}