题解打击犯罪

Posted kcn999

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解打击犯罪相关的知识,希望对你有一定的参考价值。

题目描述

        某个地区有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(打击犯罪团伙)

        技术图片

 

题解

        我们可以倒序枚举,从$n$枚举到$1$。

        当我们枚举到$i$的时候,我们就合并满足$i < j$的边$(i, j)$,合并后判断当前$i$所在集合的点数是否大于$\fracn2$即可。

技术图片
#include <iostream>
#include <cstdio>

#define MAX_N (1000 + 5)

using namespace std;

int n;
int a[MAX_N][MAX_N], l[MAX_N];
int r[MAX_N], c[MAX_N];

int Root(int x)

    int R = x, tmp;
    while(R != r[R]) R = r[R];
    while(x != r[x]) tmp = r[x], r[x] = R, x = tmp;
    return R;


void Merge(int x, int y)

    x = Root(x); 
    y = Root(y);
    r[x] = y;
    c[y] += c[x];
    c[x] = 0;
    return;


int main()

    scanf("%d", &n);
    for(register int i = 1; i <= n; ++i)
    
        scanf("%d", l + i);
        for(register int j = 1; j <= l[i]; ++j)
        
            scanf("%d", a[i] + j);
        
    
    for(register int i = 1; i <= n; ++i)
    
        r[i] = i;
        c[i] = 1;
    
    for(register int i = n; i; --i)
    
        for(register int j = 1; j <= l[i]; ++j)
        
            if(i > a[i][j]) continue;
            if(Root(i) != Root(a[i][j])) Merge(i, a[i][j]);
            if(c[Root(i)] > (n >> 1)) return printf("%d", i), 0;
        
    
    return 0;
参考程序

 

以上是关于题解打击犯罪的主要内容,如果未能解决你的问题,请参考以下文章

谷歌发布了一款AI工具,可以帮助基因组数据解读

BZOJ3994:[SDOI2015]约数个数和——题解

天梯赛每日打卡01(1-6题解)

题解报告:hdu 2059 龟兔赛跑

以亲身经历为例,我删除了代码或数据库,就是犯罪吗?

以亲身经历为例,我删除了代码或数据库,就是犯罪吗?