并查集——关押罪犯

>题目:1401关押罪犯

题目描述 S 城现有两座监狱,一共关押着N名罪犯,编号分别为1~N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。如果两名怨气值为c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c 的冲突事件。每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S 城chk 市长那里。公务繁忙的chk市长只会去看列表中的第一个事件的影响力,如果影响很坏,他就会考虑撤换警察局长。在详细考察了N名罪犯间的矛盾关系后,警察局长觉得压力巨大。他准备将罪犯们在两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。假设只要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。那么,应如何分配罪犯,才能使chk市长看到的那个冲突事件的影响力最小?这个最小值是多少?
输入 输入文件prison.in,第一行为两个正整数N和M,分别表示罪犯的数目以及存在仇恨的罪犯对数。 接下来的M 行每行为三个正整数aj,bj,cj,表示aj 号和bj号罪犯之间存在仇恨,其怨气值为cj。数据保证1 ≤aj < bj ≤N ,0 < cj ≤ 1,000,000,000,且每对罪犯组合只出现一次。 、
输出 输出文件prison.out,输出1 行,为chk市长看到的那个冲突事件的影响力。如果本年内监狱中未发生任何冲突事件,请输出0。

题目看起来很复杂,其实就是让你把囚犯放到任意一个监狱里,然后尽量让结的仇深的两名罪犯在两个不同的监狱里。
所以就先sort一下,然后利用并查集就好了。
这里还有一道类似的题目:http://10.220.121.203/judge/problem.php?id=1394

重点是如何利用并查集将囚犯分到两个不同的监狱里去,我们并不知道哪个囚犯该到哪个监狱里,也就是说我们只能做到让满足两个囚犯在不同的监狱中。

FOR(i,1,n*2)par[i]=i;
    FOR(i,1,m){
        int a=find(A[i].x),b=find(A[i].y);
        int c=find(A[i].x+n),d=find(A[i].y+n);
        if(a==b||c==d){ans=A[i].v;break;}
        par[a]=d;
        par[b]=c;
    }

建立与i对应的虚点n+i
满足:
a与b不在一个集合
c与d不在同一个集合
a与c不在同一个集合
b与d不在同一个集合
b和c为同一个集合
a和d为同一个集合

ps:关于par的合并是比较随意的 可以par[a]=d 也可以 par[d]=a

你可能感兴趣的:(题解,数据结构,——并查集)