动规(20)-并查集基础题——打击犯罪
Posted H_Cisco
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动规(20)-并查集基础题——打击犯罪相关的知识,希望对你有一定的参考价值。
【问题描述】
某个地区有n(n<=1000)个犯罪团伙,当地警方按照他们的危险程度由高到低给他们编号为1-n,他们有些团伙之间有直接联系,但是任意两个团伙都可以通过直接或间接的方式联系,这样这里就形成了一个庞大的犯罪集团,犯罪集团的危险程度唯一由集团内的犯罪团伙数量确定,而与单个犯罪团伙的危险程度无关(该犯罪集团的危险程度为n)。现在当地警方希望花尽量少的时间(即打击掉尽量少的团伙),使得庞大的犯罪集团分离成若干个较小的集团,并且他们中最大的一个的危险程度不超过n/2。为达到最好的效果,他们将按顺序打击掉编号1到k的犯罪团伙,请编程求出k的最小值。
【输入格式】black.in
第一行一个正整数n。接下来的n行每行有若干个正整数,第一个整数表示该行除第一个外还有多少个整数,若第i行存在正整数k,表示i,k两个团伙可以直接联系。
【输出格式】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)-并查集基础题——打击犯罪的主要内容,如果未能解决你的问题,请参考以下文章