贪心 + 并查集 之 CODE[VS] 1069 关押罪犯 2010年NOIP全国联赛提高组


/*
贪心 + 并查集 之 CODE[VS] 1069 关押罪犯  2010年NOIP全国联赛提高组

两座监狱,M组罪犯冲突,目标:第一个冲突事件的影响力最小。
	依据冲突大小,将M组罪犯按从大到小排序,按照排序结果,依次把每组罪犯分开放入两个监狱,
	直到当前这组罪犯已经在同一个监狱中了,此时即为答案。

实现:    1)通过不在同一个监狱的罪犯,推断出在同一个监狱的罪犯。(依据:一共就两个监狱)
	       ftr[b] = a+n   // a和b是在不同监狱
                  ftr[c] = a+n   // a和c是在不同监狱
		  => b和c根节点相同,在同一个监狱的
		据此可以判断当前这组罪犯是否已经在同一个监狱中了。

	  2)a,b不能在一个监狱,则a的根节点和b的根节点不能在同一个监狱
		  eg:假设a的根节点c,b的根节点d
			 a-c 不可
			 b-d 不可
			 a-b 不可
			 => c-d不可,故ftr[c]=d,ftr[d]=c

ftr[x] = x  //x尚未分配监狱
ftr[x] > n  //x已分配监狱

*/
 
  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <cstddef>
  5 #include <iterator>
  6 #include <algorithm>
  7 #include <string>
  8 #include <locale>
  9 #include <cmath>
 10 #include <vector>
 11 #include <cstring>
 12 #include <map>
 13 #include <utility>
 14 #include <queue>
 15 #include <stack>
 16 #include <set>
 17 #include <functional>
 18 using namespace std;
 19 typedef pair<int, int> P;
 20 const int INF = 0x3f3f3f3f;
 21 const int modPrime = 3046721;
 22 const double eps = 1e-9;
 23 const int MaxN = 20010;
 24 const int MaxM = 100010;
 25
 26 int N, M;
 27 struct Node
 28 {
 29     int a, b, c;
 30 };
 31
 32 Node nodeVec[MaxM];
 33
 34 bool Cmp(const Node n1, const Node n2)
 35 {
 36     return n1.c > n2.c;
 37 }
 38
 39 /**************************************/
 40 //Union-Find Sets
 41
 42 int ftr[MaxN << 1];
 43
 44 void ufsIni(int n)
 45 {
 46     for (int i = 0; i <= n; ++i)
 47     {
 48         ftr[i] = i;
 49     }
 50 }
 51
 52 int ufsFind(int x)
 53 {
 54     if (x == ftr[x])
 55     {
 56         return x;
 57     }
 58     return ftr[x] = ufsFind(ftr[x]);
 59 }
 60 /**************************************/
 61
 62
 63 void Solve()
 64 {
 65     int ans = 0;
 66     ufsIni((N << 1));
 67     int x, y;
 68     for (int i = 0; i < M; ++i)
 69     {
 70         x = ufsFind(nodeVec[i].a);
 71         y = ufsFind(nodeVec[i].b);
 72         if (x == y)
 73         {
 74             ans = nodeVec[i].c;
 75             break;
 76         }
 77         ftr[x] = ufsFind(nodeVec[i].b + N);
 78         ftr[y] = ufsFind(nodeVec[i].a + N);
 79     }
 80     printf("%d\n", ans);
 81 }
 82
 83 int main()
 84 {
 85 #ifdef HOME
 86     freopen("in", "r", stdin);
 87     //freopen("out", "w", stdout);
 88 #endif
 89
 90     scanf("%d %d", &N, &M);
 91     for (int i = 0; i < M; ++i)
 92     {
 93         scanf("%d %d %d", &nodeVec[i].a, &nodeVec[i].b, &nodeVec[i].c);
 94     }
 95     sort(nodeVec, nodeVec + M, Cmp);
 96     Solve();
 97
 98 #ifdef HOME
 99     cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl;
100     _CrtDumpMemoryLeaks();
101 #endif
102     return 0;
103 }

 
时间: 2024-08-02 02:49:23

贪心 + 并查集 之 CODE[VS] 1069 关押罪犯 2010年NOIP全国联赛提高组的相关文章

codevs 1069 关押罪犯 2010年NOIP全国联赛提高组

时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极 不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨 气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之 间的积怨越多.如果两名怨气值为c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并 造成影响力为c 的冲突事件. 每年年末,警察局

棋盘型动态规划 之 CODE[VS] 1169 传纸条 2008年NOIP全国联赛提高组

/* 这道题要解决两个问题 1)状态和状态方程 2)怎么保证每走一步,所形成的路径不相交,以保证最后生成的完整路径不相交. (1)状态: dp[i][j][k][l] = 小渊传递的纸条到[i][j]的位置,小轩传递的纸条到[k][l]的位置时,好心程度和的最大值. (2)状态方程: 看到题目,直接的想法是: 按题意,小渊从左上角->右下角,小轩从右下角->左上角.但是,路径在走的时候,怎么才能保证路径不相交,我想不出来办法了... 仔细想,题目要求: 两条路径的头尾坐标相同(出发点选择不同)

CODE[VS] 1098 均分纸牌 ( 2002年NOIP全国联赛提高组)

arr[i] :表示每个牌堆的纸牌的数目 平均值 :当纸牌数都一样多时,纸牌的数目 从左向右考虑,每堆纸牌有三种状态: 1) arr[i] == 平均值,考虑arr[i+1] 2) arr[i] < 平均值,此时由arr[i+1]移给arr[i]纸牌. => 移动纸牌数:(平均值 - arr[i])张    注:   考虑此时,arr[i]缺牌,那么i右边的牌堆必然多牌,无论哪堆多牌,必然有由arr[i+1]将牌移给arr[i]的过程. 3) arr[i] > 平均值,此时由arr[i]

【1083】code[vs] 1083 Cantor表 1999年NOIP全国联赛普及组

嘿嘿嘿,又是一发水题…… [传送门]:http://codevs.cn/problem/1083/ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>原题>>>>>>>>>>>>>>>>>>>>

划分型动态规划 之 CODE[VS] 1040 统计单词个数 2001年NOIP全国联赛提高组

/* dp[i][k] := 前i+1个字符组成的字符串,划分为k份,每份中包含的单词个数加起来总数的最大值. 初始化: dp[][] = -0x3f3f3f3f   // 注意:对于dp[i][k],若(i+1)<k,则dp[i][k]的值不存在,设为-0x3f3f3f3f.例如:dp[0][2] = -0x3f3f3f3f  dp[i][1] = val[0][i]   //注:val[i][j] := 截取原字符串[从i到j的字符(包含i和j位置的字符)]组成字符串,返回其包含的单词个数

划分型动态规划 之 CODE[VS] 1039 数的划分 2001年NOIP全国联赛提高组

/* dp[i][k] := 将整数i分成k份,分法种数 初始化: dp[][] = { 0 } dp[i][1] = 1 状态方程: dp[i][k] = dp[i-1][k-1] + dp[i-k][k] 思想:(引自byvoid大神的博客:https://www.byvoid.com/blog/noip-allsolutions#.E6.95.B0.E7.9A.84.E5.88.92.E5.88.86) 每种拆分方案中,最小的数为w,按照w的不同,我们可以把拆分方案分成2类: w=1,我们

code vs 1094 FBI树 2004年NOIP全国联赛普及组

题目描述 Description 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全“1”串称为I串,既含“0”又含“1”的串则称为F串. FBI树是一种二叉树[1],它的结点类型也包括F结点,B结点和I结点三种.由一个长度为2N的“01”串S可以构造出一棵FBI树T,递归的构造方法如下: 1) T的根结点为R,其类型与串S的类型相同: 2) 若串S的长度大于1,将串S从中间分开,分为等长的左右子串S1和S2:由左子串S1构造R的左子树T1,由右子串S2构造R的右子树T2.

棋盘型动态规划 之 CODE[VS] 1010 过河卒 2002年NOIP全国联赛普及组

/* dp[i][j] := 从起点[0][0]到坐标为[i][j]的位置,路径的条数. 卒行走规则:可以向下.或者向右,故 dp[i][j] = dp[i-1][j] + dp[i][j-1] (向下)      (向右) 注意: 去掉对方马的控制点 附: codevs测试数据有些弱,可以考虑到这里评测一下:清橙 (主要区别在于,dp[][]数据类型设为long long) */ 1 #include <iostream> 2 #include <cstdlib> 3 #incl

codevs 1069关押罪犯

传送门 1069 关押罪犯 2010年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamon 题目描述 Description S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极 不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨 气值"(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之 间的积怨越多.如果两名怨气值为c 的罪犯被关押在同一监狱,他