某個地區有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
1
輸出1(打擊掉紅色團伙
數據范圍及提示 Data Size & Hintn<=1000
思路:逆向+分治
這樣退出來的一定是最小值
具體為什麼自己代入一組數據看看就全明白了
非語言能形容
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 struct node 6 { 7 int u; 8 int v; 9 int w; 10 int next; 11 }edge[10001]; 12 int head[1001]; 13 int num=1; 14 int map[1001][1001]; 15 int vis[10001]; 16 int tot;//記錄每次搜索時所能搜索到的點的數量 17 int n; 18 void add(int x,int y) 19 { 20 map[x][y]=1; 21 map[y][x]=1; 22 } 23 void dfs(int x) 24 { 25 vis[x]=1; 26 tot++; 27 for(int i=1;i<=n;i++) 28 { 29 if(map[x][i]==1&&vis[i]==0) 30 { 31 dfs(i); 32 } 33 } 34 } 35 36 int main() 37 { 38 39 scanf("%d",&n); 40 for(int i=1;i<=n;i++) 41 head[i]=-1; 42 for(int i=1;i<=n;i++) 43 { 44 int m; 45 scanf("%d",&m); 46 for(int j=1;j<=m;j++) 47 { 48 int p; 49 scanf("%d",&p); 50 edge[num].u=i; 51 edge[num].v=p; 52 //edge[num].w=p; 53 edge[num].next=head[i]; 54 head[i]=num++; 55 } 56 } 57 /*for(int i=1;i<=n;i++) 58 { 59 int j=head[i]; 60 while(j!=-1) 61 { 62 cout<<edge[j].v<<" "; 63 j=edge[j].next; 64 } 65 cout<<endl; 66 } 67 cout<<"********************************"<<endl; 68 for(int i=1;i<=n;i++) 69 { 70 cout<<edge[head[i]].v<<endl; 71 }*/ 72 for(int i=n;i>=1;i--) 73 { 74 int j=head[i]; 75 while(j!=-1) 76 { 77 if(edge[j].v>=i) 78 { 79 add(edge[j].v,i); 80 tot=0; 81 memset(vis,0,sizeof(vis)); 82 dfs(i); 83 if(tot>n/2) 84 { 85 cout<<i; 86 return 0; 87 } 88 } 89 j=edge[j].next; 90 } 91 } 92 cout<<-1; 93 return 0; 94 }