[NOI2001]食物链(并查集拓展域)&& [HAOI2006]旅行(Kruskal)
题目描述
动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形。A 吃 B,B
吃 C,C 吃 A。
现有 N 个动物,以 1 - N 编号。每个动物都是 A,B,C 中的一种,但是我们并不知道
它到底是哪一种。
有人用两种说法对这 N 个动物所构成的食物链关系进行描述:
第一种说法是“1 X Y”,表示 X 和 Y 是同类。
第二种说法是“2 X Y”,表示 X 吃 Y 。
此人对 N 个动物,用上述两种说法,一句接一句地说出 K 句话,这 K 句话有的是真
的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
• 当前的话与前面的某些真的话冲突,就是假话
• 当前的话中 X 或 Y 比 N 大,就是假话
• 当前的话表示 X 吃 X,就是假话
你的任务是根据给定的 N 和 K 句话,输出假话的总数。
输入格式
从 eat.in 中输入数据
第一行两个整数,N,K,表示有 N 个动物,K 句话。
第二行开始每行一句话(按照题目要求,见样例)
输出格式
输出到 eat.out 中
一行,一个整数,表示假话的总数。
emmmmm, 最近学了并查集, 并查集能维护连通性和传递性, 这道题假如单单用一个并查集来维护谁与谁是同类, 显然无法判断互相吃的情况, 那么就容易想到用三个并查集去维护, 我们把每个动物x拆成3个节点, 分别表示同类域, 捕食域, 天敌域。假如x与y是同类, 那么x, y捕食的物种和天敌都是一样的, 把他们都合并。 而当x吃y时, 合并x的捕食域和y的同类域, x的同类域和y的天敌域, x的天敌域和y的捕食域。 在处理每句话之前, 首先要判断这句话是否为真。
#include <bits/stdc++.h> using namespace std; typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 5e4 + ;
const int MAXM = 3e3 + ;
const double eps = 1e-; template < typename T > inline void read(T &x) {
x = ; T ff = , ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') ff = -;
ch = getchar();
}
while (isdigit(ch)) {
x = (x << ) + (x << ) + (ch ^ );
ch = getchar();
}
x *= ff;
} template < typename T > inline void write(T x) {
if (x == ) {
putchar('');
return ;
}
if (x < ) putchar('-'), x = -x;
static T tot = , ch[];
while (x) {
ch[++tot] = x % + '';
x /= ;
}
while (tot) putchar(ch[tot--]);
} int n, m, ans, fa[MAXN * ]; inline int get(int x) {
return x == fa[x] ? x : fa[x] = get(fa[x]);
} int main() {
// freopen("1.in", "r", stdin);
read(n); read(m);
for (int i = ; i <= n * ; ++i) fa[i] = i;
while (m--) {
// printf("ans = %d\n", ans);
int op, x, y;
read(op); read(x); read(y);
if (x > n || y > n) {
++ans;
continue;
};
if (op == ) {
if (get(x + n) == get(y) || get(x) == get(y + n)) ++ans;
else {
fa[get(x)] = get(y);
fa[get(x + n)] = get(y + n);
fa[get(x + n + n)] = get(y + n + n);
} } else {
if (get(x) == get(y) || get(x) == get(y + n)) ++ans;
else {
fa[get(x + n)] = get(y);
fa[get(x + n + n)] = get(y + n);
fa[get(x)] = get(y + n + n);
}
}
}
write(ans);
return ;
}
题目描述
Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光。Z小镇附近共有N个景点(编号为1,2,3,…,N),这些景点被M条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路。也许是为了保护该地的旅游资源,Z小镇有个奇怪的规定,就是对于一条给定的公路Ri,任何在该公路上行驶的车辆速度必须为Vi。速度变化太快使得游客们很不舒服,因此从一个景点前往另一个景点的时候,大家都希望选择行使过程中最大速度和最小速度的比尽可能小的路线,也就是所谓最舒适的路线。
输入格式
第一行包含两个正整数,N和M。
接下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向公路,车辆必须以速度v在该公路上行驶。
最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。
输出格式
如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。
emmmmmm, 刚看到这到题的时候, 我就想到了最小差值生成树, 这是我很早之前就做过的题了, 这个题算法上写着并查集, 我当时就想Kruskal和并查集有什么关系, 就专心致志的打我的dfs去了(我丢, 我好sb。。。),dfs的思路还是很容易想到的, 从s这个点开始枚举每一条路径, 把路径上所有边的最大最小值都记录下来, 当到t这个点是时候比较就可以了, 然后我就神奇的MLE, 在一些神仙讨论是数组开小还是爆内存的时候, 我默默地把dfs改成bfs, 结果依然MLE。 算了, 放弃这个暴力吧。 一位大佬提醒我一句, 把每条边加进去, 判断图是否连通。 此时我好像幡然醒悟, 这不就是一个裸的Kruskal嘛, 然后, 我也就真的打了一个Kruskal, 我丢, 我是没睡醒嘛, (其实确实有点瞌睡), 稍作修改就A掉了。 可以说这是一道写过的题了, 我甚至还hack正解, 在以后的学习中还是要学以致用啊。。。。
#include <bits/stdc++.h> using namespace std; typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 5e5 + ;
const int MAXM = 3e3 + ;
const double eps = 1e-; template < typename T > inline void read(T &x) {
x = ; T ff = , ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') ff = -;
ch = getchar();
}
while (isdigit(ch)) {
x = (x << ) + (x << ) + (ch ^ );
ch = getchar();
}
x *= ff;
} template < typename T > inline void write(T x) {
if (x == ) {
putchar('');
return ;
}
if (x < ) putchar('-'), x = -x;
static T tot = , ch[];
while (x) {
ch[++tot] = x % + '';
x /= ;
}
while (tot) putchar(ch[tot--]);
} //bool cur1; int n, m, s, t, q1, q2, fa[MAXN];
struct tree {
int x, y, v;
bool operator < (const tree &a) const {
return v < a.v;
}
}T[]; inline int gcd(int x, int y) {
return x == ? y : gcd(y % x, x);
} inline int get(int x) {
return fa[x] == x ? x : fa[x] = get(fa[x]);
} inline void Kruskal(int ss) {
for (int i = ; i <= n; ++i) {
fa[i] = i;
}
int maxx = -INF, minn = INF;
for (int i = ss; i <= m; ++i) {
int xx = get(T[i].x), yy = get(T[i].y);
if (xx != yy) {
fa[xx] = yy;
maxx = max(maxx, T[i].v);
minn = min(minn, T[i].v);
}
xx = get(s), yy = get(t);
if (xx == yy) break;
}
int xx = get(s), yy = get(t);
if (xx == yy) {
if ((double) maxx / minn < (double) q1 / q2)
q1 = maxx, q2 = minn;
}
} int main() {
read(n), read(m);
for (int i = ; i <= m; ++i) {
read(T[i].x);
read(T[i].y);
read(T[i].v);
}
read(s); read(t);
sort(T + , T + m + );
q1 = INF, q2 = ;
for (int i = ; i <= m; ++i) Kruskal(i);
if (q1 == INF) puts("IMPOSSIBLE");
else {
int g = gcd(q1, q2);
q1 /= g, q2 /= g;
write(q1);
if (q2 != ) putchar('/'), write(q2);
}
return ;
}
[NOI2001]食物链(并查集拓展域)&& [HAOI2006]旅行(Kruskal)的更多相关文章
- 【Luogu P2024&P1892】食物链&团伙(并查集拓展域)
Luogu P1892 Luogu P2024 这两道一眼看过去很容易发现可以用并查集来做--但是当我们仔细阅读题面后,会发现其实并没有那么简单. 我们知道并查集可以很轻松地维护具有传递性的信息,也就 ...
- P2024 [NOI2001]食物链 并查集
题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种,但是我 ...
- Luogu P2024 [NOI2001]食物链 | 并查集
题目链接 思路:并查集,因为一开始我们并不知道每一只动物是哪一个种类的,所以我们干脆建立三倍于n的空间,1~n这三分之一用来存第i只动物是A的情况,n+1~2n这三分之一用来存第(i-n)只动物是B的 ...
- POJ 1703 Find them, Catch them(并查集拓展)
Description The police office in Tadu City decides to say ends to the chaos, as launch actions to ro ...
- 编程算法 - 食物链 并查集 代码(C)
食物链 并查集 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 有N仅仅动物, 分别编号为1,2,...,N. 全部动物都属于A,B,C中的一种 ...
- C++食物链【NOI2001】 并查集+建虚点
B. 食物链[NOI2001] 内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 动物王国中有三类动物A,B,C,这三类动物的食物链构成了 ...
- 【poj1182】食物链--并查集扩展域
Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 109341 Accepted: 33191 Description 动物 ...
- [poj1182]食物链(并查集+补集)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 64841 Accepted: 19077 Description ...
- POJ 1182 (经典食物链 /并查集扩展)
(參考他人资料) 向量偏移--由"食物链"引发的总结 http://poj.org/problem?id=1182这道食物链题目是并查集的变型.非常久曾经做的一次是水过的,这次 ...
随机推荐
- Fliptile POJ-3279 DFS
题目链接:Fliptile 题目大意 有一个01矩阵,每一次翻转(0->1或者1->0)一个元素,就会把与他相邻的四个元素也一起翻转.求翻转哪些元素能用最少的步骤,把矩阵变成0矩阵. 思路 ...
- 对Servlet执行流程的初步认识
这里我们以Post方式请求Serclet为例 1.找到 中的URL地址 Form表单的Post请求HelloServlet(Action="HelloServlet")发起时, A ...
- Python 编译器与解释器
Python 编译器与解释器 Python的环境我们已经搭建好了,可以开始学习基础知识了.但是,在此之前,还要先说说编译器与解释器相关的内容. 如果这部分内容,让你觉得难以理解或不能完全明白,可以暂时 ...
- Kurskal算法
Kruskal算法是以边为主要关注对象的最小生成树算法,是最小生成树最佳的算法实现. 其时间复杂度为O(ElogE)(E为边的数量),而Prime算法采用邻接矩阵的方法是O(V^2)(V为顶点数量). ...
- Hadoop源代码点滴-系统结构(HDFS+YARN)
Hadoop建立起HDFS和YARN两个字系统,前者是文件系统,管数据存储:后者是计算框架,管数据处理. 如果只有HDFS而没有YARN,那么Hadoop集群可以被用作容错哦的文件服务器,别的就没有什 ...
- Python将自己写的模块进行打包
将项目打包成模块的想法来自于flask文档教程,这不是在PyCon上和阿明合了照嘛,这不得多看看人家的东西.有兴趣的可以看看文档的项目可安装化部分,作者将flask项目打包成一个包,使其可以再任何地方 ...
- ELK 学习笔记之 elasticsearch elasticsearch.yml配置概述
elasticsearch.yml配置概述: 设置集群名字 cluster.name 定义节点名称 node.name 节点作为master,但是不负责存储数据,只是协调. node.master: ...
- Java8 Stream性能如何及评测工具推荐
作为技术人员,学习新知识是基本功课.有些知识是不得不学,有些知识是学了之后如虎添翼,Java8的Stream就是兼具两者的知识.不学看不懂,学了写起代码来如虎添翼. 在上篇<Java8 Stre ...
- 星之小说下载器Android版
原本是想在酷安上架的,然而审核不通过..只能通过网页方式宣传了 一款使用Jsoup开源库网络爬虫的APP,将在线阅读的小说解析,把小说全本下载为txt文件 由于使用爬虫技术,所以下载的速度不是很理想, ...
- Java读源码之LockSupport
前言 JDK版本: 1.8 作用 LockSupport类主要提供了park和unpark两个native方法,用于阻塞和唤醒线程.注释中有这么一段: 这个类是为拥有更高级别抽象的并发类服务的,开发中 ...