题目描述

动物王国中有三类动物 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的捕食域。 在处理每句话之前, 首先要判断这句话是否为真。

当x与y同类:
1.x的捕食域与y的同类域在同一集合, 即x吃y。
2.x的同类域和y的捕食域在同一集合, 即y吃x、
当x吃y:
1.x的同类域和y的同类域在一个集合, 即x和y是同类。
2.x的同类域和y的捕食域在一个集合, 即y吃x。
#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)的更多相关文章

  1. 【Luogu P2024&P1892】食物链&团伙(并查集拓展域)

    Luogu P1892 Luogu P2024 这两道一眼看过去很容易发现可以用并查集来做--但是当我们仔细阅读题面后,会发现其实并没有那么简单. 我们知道并查集可以很轻松地维护具有传递性的信息,也就 ...

  2. P2024 [NOI2001]食物链 并查集

    题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种,但是我 ...

  3. Luogu P2024 [NOI2001]食物链 | 并查集

    题目链接 思路:并查集,因为一开始我们并不知道每一只动物是哪一个种类的,所以我们干脆建立三倍于n的空间,1~n这三分之一用来存第i只动物是A的情况,n+1~2n这三分之一用来存第(i-n)只动物是B的 ...

  4. 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 ...

  5. 编程算法 - 食物链 并查集 代码(C)

    食物链 并查集 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 有N仅仅动物, 分别编号为1,2,...,N. 全部动物都属于A,B,C中的一种 ...

  6. C++食物链【NOI2001】 并查集+建虚点

    B. 食物链[NOI2001] 内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 动物王国中有三类动物A,B,C,这三类动物的食物链构成了 ...

  7. 【poj1182】食物链--并查集扩展域

    Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 109341   Accepted: 33191 Description 动物 ...

  8. [poj1182]食物链(并查集+补集)

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 64841   Accepted: 19077 Description ...

  9. POJ 1182 (经典食物链 /并查集扩展)

    (參考他人资料) 向量偏移--由"食物链"引发的总结 http://poj.org/problem?id=1182这道食物链题目是并查集的变型.非常久曾经做的一次是水过的,这次 ...

随机推荐

  1. Hive之行转列与列转行

    行转列 原始数据: 需求: 把星座和血型一样的人归类到一起.结果如下: 射手座,A 大海|凤姐 白羊座,A 孙悟空|猪八戒 白羊座,B 宋宋 实现: vi person_info.txt 孙悟空 白羊 ...

  2. layui table异步调用数据的时候,数据展示不出来现象解决方案

    最近使用layui table进行异步获取数据并填充的时候,控制台打印出数据长度为0,但是其中还有数据,网上找了很多办法,下边是我最后使用的. 一般,render渲染表格是独立的书写格式,但是我在做数 ...

  3. 有了 CompletableFuture,使得异步编程没有那么难了!

    本文导读: 业务需求场景介绍 技术设计方案思考 Future 设计模式实战 CompletableFuture 模式实战 CompletableFuture 生产建议 CompletableFutur ...

  4. .Net Core 商城微服务项目系列(十三):搭建Log4net+ELK+Kafka日志框架

    之前是使用NLog直接将日志发送到了ELK,本篇将会使用Docker搭建ELK和kafka,同时替换NLog为Log4net. 一.搭建kafka 1.拉取镜像 //下载zookeeper docke ...

  5. 使用Docker Toolbox基于boot2docker搭建的Docker如何修改镜像源

    镜像源 由于众所周知的原因,我们直接连接这些位于国外服务器上的仓库去获取依赖包速度是非常慢的,这时候我们通常会采用国内一些组织或开发者贡献的国内镜像仓库. 1.首先Docker也提供了国内的镜像源:h ...

  6. web前端体系-了解前端,深入前端,架构前端,再看前端。大体系-知识-小细节

    1.了解前端,深入前端,架构前端,再看前端.大体系-知识-小细节 个人认为:前端发展最终的导向是前端工程化,智能化,模块化,组件化,层次化. 2.面试第一关:理论知识. 2-1.http标准 2-2. ...

  7. Java字段初始化规律

    首先先附上一段代码:public class InitializeBlockDemo { public static void main(String[] args) { InitializeBloc ...

  8. python编程基础之九

    原码, 反码, 补码原码,即用二进制表示正数: 原码 == 反码 == 补码负数: 反码: 原码除符号位之外全部取反 补码: 反码 + 1 位运算:运算符 作用 & 按位与 | 按位或 ^ 按 ...

  9. Docker 配置国内镜像

    前言 当我们使用Docker pull 拉取镜像时,有时候因网络问题,导致获取镜像报错,如下 :Error response from daemon:Get https://registry-1.co ...

  10. 信息传递 NOIP2015 day1 T2

    题文: 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一轮 ...