描述 Description S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。如果两名怨气值为c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c 的冲突事件。 每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S 城Z 市长那里。公务繁忙的Z 市长只会去看列表中的第一个事件的影响力,如果影响很坏,他就会考虑撤换警察局长。 在详细考察了N 名罪犯间的矛盾关系后,警察局长觉得压力巨大。他准备将罪犯们在两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。假设只要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。那么,应如何分配罪犯,才能使Z 市长看到的那个冲突事件的影响力最小?这个最小值是多少? 输入格式 Input Format 输入文件的每行中两个数之间用一个空格隔开。 第一行为两个正整数N 和M,分别表示罪犯的数目以及存在仇恨的罪犯对数。 接下来的M 行每行为三个正整数aj,bj,cj,表示aj 号和bj 号罪犯之间存在仇恨,其怨气值为cj。数据保证1<=aj<bj<N,0<cj<=1,000,000,000 且每对罪犯组合只出现一次。 输出格式 Output Format 输出共1 行,为Z 市长看到的那个冲突事件的影响力。如果本年内监狱中未发生任何冲突事件,请输出0。 数据范围 对于30%的数据有N≤15。 对于70%的数据有N≤2000,M≤50000。 对于100%的数据有N≤20000,M≤100000。 这是一道并查集的问题。可想到按照从大到小排序,然后依次处理,一旦遇到矛盾,那便是最大的矛盾。 #include <cstdio> #include <algorithm> using namespace std; struct edge { int x, y; int value; }; edge prison[100000 + 5]; int pre[20000 + 5]; int ensure[2000 + 5]; int m, n; bool cmp(edge a, edge b) { return a.value > b.value; } int FindFather(int x) { int r = x; while (r != pre[r]) ///找到根节点 r = pre[r]; int i = x; int j; while (i != r) ///进行路径压缩 { j = pre[i]; pre[i] = r; i = j; } return r; } void Mix(int a, int b) ///合并 { int fx = FindFather(a); int fy = FindFather(b); if (fx != fy) pre[fy] = fx; } int main() { int xx, yy; scanf("%d%d", &n, &m); for (int i = 1; i <= m; ++i) scanf("%d%d%d", &prison[i].x, &prison[i].y, &prison[i].value); sort(prison + 1, prison + m+1, cmp); ///从大到小排序 for (int i = 1; i <= n; ++i) ///初始化 { pre[i] = i; ensure[i] = 0; } for (int i = 1; i <= m; ++i) { xx = prison[i].x; yy = prison[i].y; int fx = FindFather(xx); int fy = FindFather(yy); if (fx == fy) ///一旦遇到矛盾就输出 { printf("%d\n", prison[i].value); return 0; } if (ensure[xx] == 0) ///如果 xx 还没有矛盾对象,则设置矛盾对象 ensure[xx] = yy; else ///如果有矛盾对象,把 yy 和矛盾对象合并 Mix(yy, ensure[xx]); if (ensure[yy] == 0) ///同上 ensure[yy] = xx; else ///同上 Mix(xx, ensure[yy]); } printf("0\n"); return 0; } 在网上还碰见了40行AC的大牛,贴一下代码表示崇敬。#include <algorithm> #include <iostream> using namespace std; int n,m,f[40001],x,y; struct data { int a,b,c; }e[100001]; int gz(const data &a,const data &b) { if(a.c>b.c)return 1; else return 0; } int find(int x) { return f[x]==x?x:f[x]=find(f[x]); } int main() { cin>>n>>m; for(int i=1;i<=m;i++) cin>>e[i].a>>e[i].b>>e[i].c; for(int i=1;i<=n*2;i++) f[i]=i; sort(e+1,e+m+1,gz); for(int i=1;i<=m;i++) { x=find(e[i].a); y=find(e[i].b); if(x==y) { cout<<e[i].c; return 0; } f[y] = find(e[i].a + n); f[x] = find(e[i].b + n); } cout<<0; return 0; }
出处:http://hzwer.com/599.html
NOIP - 关押罪犯
最新推荐文章于 2023-11-27 13:18:38 发布