zoukankan      html  css  js  c++  java
  • GHOJ 699 打击犯罪

    题目描述

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

            Failed to load picture

    题解

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

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

    #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;
    }
    参考程序
  • 相关阅读:
    C# 两个窗体中相互切换的方法
    Linq对DataTable数据的分组统计
    如何让窗体大小随着控件的大小变化而变化
    两张表解决用户自定义数据库之思路
    picturebox显示用字符串代表图片名称的(已导入资源的)图片
    如何将access高版本数据库保存为低版本的?
    Microsoft.Jet.OLEDB.4.0和Microsoft.ACE.OLEDB.12.0的区别
    条件编译解决AutoCAD多版本问题
    一个爬取股票信息的爬虫程序
    Python爬虫抓取东方财富网股票数据并实现MySQL数据库存储
  • 原文地址:https://www.cnblogs.com/kcn999/p/10990524.html
Copyright © 2011-2022 走看看