4602: [Sdoi2016]齿轮

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 613  Solved: 324
[Submit][Status][Discuss]

Description

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

Input

有多组数据,第一行给定整数T,表示总的数据组数,之后依次给出T组数据。每一组数据的第一行给定整数N和
M,表示齿轮总数和链条总数。之后有M行,依次描述了每一个链条,其中每一行给定四个整数u,v,x和y,表示
只考虑这一组联动关系的情况下,编号为u的齿轮转动x圈,编号为v的齿轮会转动y圈。请注意,x为正整数,而y为
非零整数,但是y有可能为负数。
T<=32,N<=1000,M<=10000且x与y的绝对值均不超过100
 

Output

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

Sample Input

2
3 3
1 2 3 5
2 3 5 -7
1 3 3 -7
3 3
1 2 3 5
2 3 5 -7
1 3 3 7

Sample Output

Case #1: Yes
Case #2: No

HINT

 

Source

【民间做法】:DFS
//对于每组齿轮(u, v)连边,权值为y/x(反向边x/y)
//dfs 判断矛盾
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef double real;
inline void read(int &x){
register char ch=getchar();int f=1;x=0;
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
x*=f;
}
const int N=1e5+5;
const real eps=1e-6;
struct edge{int v,next;real w;}e[N<<1];int tot,head[N];
int T,n,m,cas;
bool vis[N],flag;
real val[N];
inline void add(int x,int y,real z){
e[++tot].v=y;e[tot].w=z;e[tot].next=head[x];head[x]=tot;
}
inline bool dfs(int x,real sp){
vis[x]=1;
val[x]=sp;
for(int i=head[x];i;i=e[i].next){
if(!vis[e[i].v]){
if(dfs(e[i].v,sp*e[i].w))
return 1;
}
else{
if(fabs(val[e[i].v]-sp*e[i].w)>eps)
return 1;
}
}
return 0;
}
inline void clr(){
tot=0;flag=0;
memset(head,0,(n+1)<<2);
memset(vis,0,(n+1)<<2);
}
int main(){
for(read(T);T--;clr()){
read(n);read(m);
for(int i=1,u,v,x,y;i<=m;i++){
read(u);read(v);
read(x),read(y);
add(u,v,(real)y/(real)x);
add(v,u,(real)x/(real)y);
}
for(int i=1;i<=n;i++) if(!vis[i]){
if(dfs(i,1)){
flag=1;break;
}
}
printf("Case #%d: %s\n",++cas,flag?"No":"Yes");
}
return 0;
}
【官方做法】:加权并查集

首先可以看出这个齿轮的转动关系是具有传递性的,如果知道x和y的关系,也知道y和z的关系,就可以推出x和z的关系。具有这种关系的东西一般都可以用加权并查集来搞。对于每个元素给它维护一个dis[x],表示的含义是如果x的代表元素转动1圈,x要转动几圈。每次读入一个限制如果x和y不在同一个集合里就进行合并。合并的时候先找到x的代表元素r1和y的代表元素r2,然后我们要把r2合并到r1上。要进行合并就要知道r1转一圈的时候r2转几圈。设从读入的信息可以知道x转一圈的时候y转w圈,那么如果r1转了一圈,y就转了dis[x]∗w圈;而当y转了dis[x]∗w圈的时候,r2转了dis[x]∗w/dis[y]圈。关系如下图:
 
如果读入的x和y在一个集合里,那么就可以用维护的信息算出x转了一圈的时候y转了几圈,和读入的信息进行比对就可以判定是否发生矛盾。

这个数据范围看起来好像很小的样子。。但是如果它出上n-1个信息,每次都是当齿轮i转动1圈的时候齿轮i+1转动100圈,那么最后就会发现当齿轮1转动一圈的时候齿轮n会转动100n圈。。这样的话就不能直接用int或者long
long或者什么类似的东西来维护加权并查集的dis了。。用分解质因数似乎是比较稳的方法,但是听说用long double还是什么类似的东西也能过?

#include<cmath>
#include<cstdio>
using namespace std;
typedef double real;
inline void read(int &x){
register char ch=getchar();int f=1;x=0;
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
x*=f;
}
const int N=1e5+5;
const real eps=1e-6;
int T,n,m,cas;bool flag;
int fa[N];real dis[N];
int find(int x){
int t;
if(fa[x]!=x) t=find(fa[x]),dis[x]*=dis[fa[x]],fa[x]=t;
return fa[x];
}
int main(){
for(read(T);T--;flag=0){
read(n);read(m);
for(int i=1;i<=n;i++) fa[i]=i,dis[i]=1;
for(int i=1,r1,r2,u,v,x,y;i<=m;i++){
read(u);read(v);read(x);read(y);
r1=find(u);r2=find(v);
if(r1==r2){
if(fabs(dis[v]/dis[u]-(real)y/(real)x)>eps){
flag=1;break;
}
}
else{
fa[r2]=r1;
dis[r2]=(dis[u]*y)/(dis[v]*x);
}
}
printf("Case #%d: %s\n",++cas,flag?"No":"Yes");
}
return 0;
}

[Sdoi2016]齿轮的更多相关文章

  1. BZOJ 4602: [Sdoi2016]齿轮 dfs

    4602: [Sdoi2016]齿轮 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4602 Description 现有一个传动系统,包 ...

  2. BZOJ4602 Sdoi2016 齿轮 【带权并查集】*

    BZOJ4602 Sdoi2016 齿轮 Description 现有一个传动系统,包含了N个组合齿轮和M个链条.每一个链条连接了两个组合齿轮u和v,并提供了一个传动比x : y.即如果只考虑这两个组 ...

  3. bzoj 4602: [Sdoi2016]齿轮

    4602: [Sdoi2016]齿轮 Description 现有一个传动系统,包含了N个组合齿轮和M个链条.每一个链条连接了两个组合齿轮u和v,并提供了一个传动比x  : y.即如果只考虑这两个组合 ...

  4. BZOJ4602:[SDOI2016]齿轮(并查集)

    Description 现有一个传动系统,包含了N个组合齿轮和M个链条.每一个链条连接了两个组合齿轮u和v,并提供了一个传动比x  : y.即如果只考虑这两个组合齿轮,编号为u的齿轮转动x圈,编号为v ...

  5. 【bzoj4602】[Sdoi2016]齿轮 BFS

    题目描述 给出一张n个点m条边的有向图,每条边 (u,v,x,y) 描述了 u 的点权乘 x 等于 v 的点权乘 y (点权可以为负).问:是否存在满足条件的图. 输入 有多组数据,第一行给定整数T, ...

  6. BZOJ4602 SDOI2016齿轮(搜索)

    dfs一遍给每个齿轮随便标个值看是否矛盾就行了. #include<iostream> #include<cstdio> #include<cmath> #incl ...

  7. bzoj4602 [Sdoi2016]齿轮

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4602 [题解] 对于每组齿轮(u, v)连边,权值为y/x(反向边x/y) 那么直接dfs计 ...

  8. [bzoj4602][Sdoi2016]齿轮——dfs

    题目 现有一个传动系统,包含了N个组合齿轮和M个链条.每一个链条连接了两个组合齿轮u和v,并提供了一个传动比x : y.即如果只考虑这两个组合齿轮,编号为u的齿轮转动x圈,编号为v的齿轮会转动y圈.传 ...

  9. NC20583 [SDOI2016]齿轮

    题目链接 题目 题目描述 现有一个传动系统,包含了N个组合齿轮和M个链条.每一个链条连接了两个组合齿轮u和v,并提供了一个传动比x : y. 即如果只考虑这两个组合齿轮,编号为u的齿轮转动x圈,编号为 ...

随机推荐

  1. linux下nginx配置ssl证书(https)

    nginx配置ssl很简单,首先需要两个文件,一个是crt文件,另一个是key文件,如下所示: xxx.crt;  #(证书公钥)xxx.key; #(证书私钥) 把这两个文件放到nginx的conf ...

  2. spring mvc实现接口参数统一更改

    适用于post  json方式提交 使用map接收的接口参数更改. 使用@Aspect实现:

  3. iOS : Blur Effect

    http://blog.bubbly.net/2013/09/11/slick-tricks-for-ios-blur-effect/ Full sample sources available at ...

  4. 通过tarball形式安装HBASE Cluster(CDH5.0.2)——HBASE 真分布式集群配置

    一.应该先配置好zookeeper并成功启动,否则hbase无法启动 二.配置HBASE集群 1,配置hbase-env.sh,下面是最少配置项目 [hadoop@zk1 conf]$ vim hba ...

  5. JUnit 3一个例子就懂

    JUnit is a simple framework to write repeatable tests. It is an instance of the xUnit architecture f ...

  6. Android学习笔记——Intents 和 Intent Filters(二)

    本人邮箱:JohnTsai.Work@gmail.com,欢迎交流讨论. 欢迎转载,转载请注明网址:http://www.cnblogs.com/JohnTsai/p/3993488.html 知识点 ...

  7. 在Lua中计算含中文的字符串的长度

    --[[ @desc: 计算字符串字符个数 author:{author} time:-- :: --@inputstr: 源字符串 return 字符个数 ]] function getString ...

  8. 多页Excel转换成PDF时如何保存为单独文件

    通过ABBYY PDF Transformer+图文识别软件,使用PDF-XChange打印机将多页Excel工作簿转换成PDF文档(相关文章请参考ABBYY PDF Transformer+从MS ...

  9. IIS------如何占用80端口

    如何占用80端口 请看我的一篇随笔: https://www.cnblogs.com/tianhengblogs/p/9292347.html

  10. 5 -- Hibernate的基本用法 --4 3 JDBC连接属性

    Hibernate需要进行数据库访问,因此必须设置连接数据库的相关属性.所有Hibernate属性的名字和语义都在org.hibernate.cfg.Environment中定义. 关于JDBC连接配 ...