noip2010关押罪犯解题报告

时间:2021-10-18 20:43:22

题目描述

  S 城现有两座*,一共关押着N 名罪犯,编号分别为1~N。他们之间的关系自然也极

不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨

气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之

间的积怨越多。如果两名怨气值为c 的罪犯被关押在同一*,他们俩之间会发生摩擦,并

造成影响力为c 的冲突事件。

每年年末,警察局会将本年内*中的所有冲突事件按影响力从大到小排成一个列表,

然后上报到S 城Z 市长那里。公务繁忙的Z 市长只会去看列表中的第一个事件的影响力,

如果影响很坏,他就会考虑撤换警察局长。

在详细考察了N 名罪犯间的矛盾关系后,警察局长觉得压力巨大。他准备将罪犯们在

两座*内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。假设只

要处于同一*内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。那

么,应如何分配罪犯,才能使Z 市长看到的那个冲突事件的影响力最小?这个最小值是少?

输入描述

第一行为两个正整数N 和M,分别表示罪犯的数目以及存在仇恨的罪犯对数。

接下来的M 行每行为三个正整数aj,bj,cj,表示aj 号和bj 号罪犯之间存在仇恨,其怨气值为cj。数据保证,且每对罪犯组合只出现一次

输出描述

共1 行,为Z 市长看到的那个冲突事件的影响力。如果本年内*

中未发生任何冲突事件,请输出0

样例输入 Sample Input

4 6

1 4 2534

2 3 3512

1 2 28351

1 3 6618

2 4 1805

3 4 12884

样例输出 

3512

【数据范围】

对于30%的数据有N≤ 15。

对于70%的数据有N≤ 2000,M≤ 50000。

对于100%的数据有N≤ 20000,M≤ 100000。

 核心程序

for(i=1;i<m+1;i++)
{
sa
=find(crime[i].a);
sb
=find(crime[i].b);
if(sa==sb)
{
ans
=i;
break;
}
else
{
f[sa]
=f[find(crime[i].b+n)];
f[sb]
=f[find(crime[i].a+n)];
}
}

数据结构分析:树形结构(二叉)

结构体:
typedef struct
{
   int a,b,anger;        
}Node;

 

算法:并查集(树形),运用递归实现。

 

思路:先给“怨气值”进行排序。

然后找最大的“怨气值”,把对应的两人分到两所*去。

再找次大的“怨气值”:(对应的两个人这时有三种情况)

1其中已经有一个人分好了*:另一个人分到另一个*。

2两个人甲乙都还没分好*:找与甲乙有怨的已经在*里的所有人,发现其中与甲最怨的是丙,与乙最怨的是丁,找出丙丁中更怨(最怨、更怨:排序顺序靠近大的一段)一点的丙,发现丙在狱1,果断把甲放到狱2,乙放到狱1。

3两个人的*都分好了:(又分两种情况)

1)两个人不同*:OK不用分了

2)两个人同一个*:看来这俩会是最大的冤家(“最终结果”求出)

【若本次没有得出“最终结果”,反复执行第3步】

 

 

#include<stdio.h>
typedef
struct
{
int a,b,anger;
}Node;

int n,m,ans;
int f[40002];
Node crime[
100001];

void qsort(int l,int r)
{
int i=l,j=r,mid=crime[(i+j)/2].anger;
while(i<=j)
{
while(crime[i].anger>mid) i++;
while(crime[j].anger<mid) j--;
if(i<=j)
{
Node t
=crime[i];
crime[i]
=crime[j];
crime[j]
=t;
i
++;
j
--;
}
}
if(i<r) qsort(i,r);
if(j>l) qsort(l,j);
}

int find(int x)
{
if(x!=f[x])
f[x]
=find(f[x]);
return f[x];
}

int main()
{
int n,m,i,j,sa,sb;
scanf(
"%d%d",&n,&m);
for(i=1;i<m;i++)
scanf(
"%d%d%d",&crime[i].a,&crime[i].b,&crime[i].anger);
qsort(
1,m);
for(i=1;i<=2*n;i++)
f[i]
=i;
for(i=1;i<m+1;i++)
{
sa
=find(crime[i].a);
sb
=find(crime[i].b);
if(sa==sb)
{
ans
=i;
break;
}
else
{
f[sa]
=f[find(crime[i].b+n)];
f[sb]
=f[find(crime[i].a+n)];
}
}
printf(
"%d",crime[ans].anger);
return 0;
}