bzoj 4602: [Sdoi2016]齿轮
4602: [Sdoi2016]齿轮
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
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
Case #2: No
题解:
dfs,按要求连边,边权即为比值,然后直接赋值搜索,遇到矛盾时退出。。
但是这题还有精度问题,随便搞一下就好了。。
#include<stdio.h> #include<iostream> using namespace std; const int N=1005; const int M=10005; #define eps 1e-8 int T,n,m,i,x,y,u,v,ok,Case,p[N]; int tot,head[N],Next[M<<1],to[M<<1]; double a[M<<1],f[N]; void add(int u,int v,double x) { tot++; to[tot]=v; a[tot]=x; Next[tot]=head[u]; head[u]=tot; } bool dfs(int x) { int i; p[x]=1; for(i=head[x];i!=-1;i=Next[i]) { int y=to[i]; if(p[y]==0) { f[y]=f[x]*a[i]; if(dfs(y)==0) return 0; } else if((f[x]*a[i]-f[y])>eps) return 0; } return 1; } int main() { scanf("%d",&T); Case=0; while(T--) { scanf("%d%d",&n,&m); tot=0; for(i=1;i<=n;i++) head[i]=-1,p[i]=0,f[i]=0; for(i=1;i<=m;i++) { scanf("%d%d%d%d",&u,&v,&x,&y); add(u,v,1.0*x/y); add(v,u,1.0*y/x); } ok=0; for(i=1;i<=n;i++) if(p[i]==0) { f[i]=1.0; if(dfs(i)==0) { ok=1; break; } } Case++; printf("Case #%d: ",Case); if(ok==0) printf("Yes\n");else printf("No\n"); } return 0; }
一念起,天涯咫尺; 一念灭,咫尺天涯。