动规(20)-并查集基础题——打击犯罪

Posted H_Cisco

tags:

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

【问题描述】

   某个地区有n(n<=1000)个犯罪团伙,当地警方按照他们的危险程度由高到低给他们编号为1-n,他们有些团伙之间有直接联系,但是任意两个团伙都可以通过直接或间接的方式联系,这样这里就形成了一个庞大的犯罪集团,犯罪集团的危险程度唯一由集团内的犯罪团伙数量确定,而与单个犯罪团伙的危险程度无关(该犯罪集团的危险程度为n)。现在当地警方希望花尽量少的时间(即打击掉尽量少的团伙),使得庞大的犯罪集团分离成若干个较小的集团,并且他们中最大的一个的危险程度不超过n/2。为达到最好的效果,他们将按顺序打击掉编号1k的犯罪团伙,请编程求出k的最小值。

【输入格式】black.in

  第一行一个正整数n。接下来的n行每行有若干个正整数,第一个整数表示该行除第一个外还有多少个整数,若第i行存在正整数k,表示ik两个团伙可以直接联系。

【输出格式】black.out

一个正整数,为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

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n, maxt, i, j, r1, r2, q, f, t;
int head[1001], s[1001], father[1001];
struct node

    int data, nex;
 p[100000];
int find(int x)

    return father[x] == x ? x : father[x] = find(father[x]);

void lian(int x, int y)

    p[++q].nex = head[x];
    p[q].data = y;
    head[x] = q;

int main()

    cin >> n;
    maxt = n / 2;
    for (i = 1; i <= n; i++)
    
        cin >> t;
        for (j = 1; j <= t; j++)
        
            cin >> f, lian(i, f);
        
    
    for (i = 1; i <= n; i++)
    
        father[i] = i;
        s[i] = 1;
    
    for (i = n; i >= 1; i--)
        for (j = head[i]; j; j = p[j].nex)
            if (p[j].data > i)
            
                r1 = find(i);
                r2 = find(p[j].data);
                if (r1 != r2) //必须判断,否则"加重 ”
                
                    father[r2] = r1;
                    s[r1] = s[r1] + s[r2];
                
                if (s[r1] > maxt)
                
                    cout << i;
                    return 0;
                
            
    return 0;

以上是关于动规(20)-并查集基础题——打击犯罪的主要内容,如果未能解决你的问题,请参考以下文章

动规(20)-并查集基础题——打击犯罪

动规(18)-并查集基础题——团伙

动规(18)-并查集基础题——团伙

动规(18)-并查集基础题——团伙

动规(24)-并查集基础题——关押罪犯

动规(24)-并查集基础题——关押罪犯