5971 打击犯罪

题目描述 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

 输出1(打击掉红色团伙

数据范围及提示 Data Size & Hint

n<=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 }
原文地址:https://www.cnblogs.com/zwfymqz/p/6701014.html