齿轮

题目大意

现有一个传动系统,包含了 N 个组合齿轮和 M 个链条。
每一个链条连接了两个组合齿轮 u 和 v ,并提供了一个传动比 。即如果只考虑这两个组合齿轮,编号为 u 的齿轮转动 x 圈,编号为 v 的齿轮会转动 y 圈。
传动比为正表示若编号为 u 的齿轮顺时针转动,则编号为 v 的齿轮也顺时针转动。传动比为负表示若编号为 u 的齿轮顺时针转动,则编号为 v 的齿轮会逆时针转动。
若不同链条的传动比不相容,则有些齿轮无法转动。我们希望知道,系统中的这个组合齿轮能否同时转动。

输入格式

有多组数据,第一行给定整数 T ,表示总的数据组数,之后依次给出 T 组数据。
每一组数据的第一行给定整数 n 和 m ,表示齿轮总数和链条总数。
之后有 M 行,依次描述了每一个链条,其中每一行给定四个整数u,v ,x 和 y,表示只考虑这一组联动关系的情况下,编号为 u 的齿轮转动 x 圈,编号为 v 的齿轮会转动 y 圈。
请注意, x 为正整数,而 y 为非零整数,但是 y 有可能为负数。

输出格式

输出 T 行,对应每一组数据。首先应该输出标识这是第几组数据,参见样例输出。
之后输出判定结果,如果N个组合齿轮可以同时正常运行,则输出Yes,否则输出No。

算法

  • 带权并查集裸题 但是之前没接触过带权并查集 考试的时候也没打出来……
  • 处理每个点到集合的代表元素的距离 这里体现为到代表元素的乘积
  • 每次在处理的时候更新一下权值 具体操作看代码注释

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
const double EPS = 1e-5;//精度

int fa[maxn];
double d[maxn];//注意必须是double类型
int flag;

int find(int x){//带权并查集 找代表元素加路径压缩 加更新权值
	if(x == fa[x])return x;
	int rt = find(fa[x]);
	d[x] *= d[fa[x]];
	return fa[x] = rt;
}

int main(){
	int T;scanf("%d",&T);
	int cnt = 0;
	while(T--){
		flag = 1;
		cnt++;
		int n,m;scanf("%d%d",&n,&m);
		for(int i = 1;i <= n;++i)fa[i] = i,d[i] = 1;
		while(m--){
			int x,y,a,b;scanf("%d%d%d%d",&x,&y,&a,&b);
			int fx = find(x),fy = find(y);
			double k = (double)a / b;
			if(fx != fy)fa[fx] = fy,d[fx] = k * d[y] / d[x];//更新 画图手模比较好理解
			else if(abs(d[x] / d[y] - k) >= EPS)flag = 0;//不能直接比较浮点数大小
		}
		if(!flag)printf("Case #%d: No
",cnt);
		else printf("Case #%d: Yes
",cnt);
	}
	return 0;
}

原文地址:https://www.cnblogs.com/2004-08-20/p/13470790.html