【bzoj4602】【SDOI2016】【齿轮】【dfs】

来源:互联网 发布:淘宝客佣金代扣 编辑:程序博客网 时间:2024/06/09 18:52

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

题解:

直接dfs精度会爆(不过貌似数据并没有爆);

可以把所有数分解质因数,处理出从一个齿轮到它连着的齿轮每个质因子变化了多少.

对于每个质因子都dfs一遍.

最后再dfs一遍正负即可.

代码:

#include<iostream>#include<cstdio>#include<cstring>#define N 1010#define M 10010using namespace std;int point[N],T,next[M<<1],n,m,cnt,t,prime[110],num,f[N],vis[N];struct use{  int x,y,a,b;}p[M];struct edge{  int st,en,v;}e[M<<1];int read(){  int f(1),x(0);  char ch=getchar();  while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}  while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();  return x*f;}void pre(){  for (int i=2;i<=100;i++){    if (!f[i]) prime[++num]=i;    for (int j=1;j<=num&&i*prime[j]<=100;j++){      f[i*prime[j]]=1;      if (i%prime[j]==0) break;     }  }}void add(int x,int y,int v){  next[++cnt]=point[x];point[x]=cnt;  e[cnt].en=y;e[cnt].v=v;}bool dfs1(int x){  for (int i=point[x];i;i=next[i])    if (vis[e[i].en]==vis[0]){      vis[e[i].en]=vis[x]+e[i].v;      if (!dfs1(e[i].en)) return 0;    }    else{     if (vis[e[i].en]!=vis[x]+e[i].v) return 0;   }     return 1;}bool dfs2(int x){  for (int i=point[x];i;i=next[i])    if (vis[e[i].en]==vis[0]){      vis[e[i].en]=vis[x]^e[i].v;      if (!dfs2(e[i].en)) return 0;    }    else{     if (vis[e[i].en]!=vis[x]^e[i].v) return 0;   }     return 1;}bool cal(){  for (int i=1;i<=num;i++){    memset(point,0,sizeof(point));cnt=0;    for (int j=1;j<=m;j++){      int a=p[j].a,b=p[j].b,t(0);      while (a%prime[i]==0){a/=prime[i];t++;}      while (b%prime[i]==0){b/=prime[i];t--;}      add(p[j].x,p[j].y,t);      add(p[j].y,p[j].x,-t);    }   memset(vis,127/3,sizeof(vis));   for (int j=1;j<=n;j++)     if (vis[j]==vis[0]){       vis[j]=0;       if (!dfs1(j)) return 0;     }  }  memset(point,0,sizeof(point));cnt=0;  for (int j=1;j<=m;j++){    int a=p[j].a,b=p[j].b,c=0;    if (a>0&&b<0||a<0&&b>0) c=1;    add(p[j].x,p[j].y,c);    add(p[j].y,p[j].x,c);   }  memset(vis,127/3,sizeof(vis));  for (int j=1;j<=n;j++)    if (vis[j]==vis[0]){      vis[j]=0;      if (!dfs2(j)) return 0;    }  return 1;}void init(){  n=read();m=read();  for (int i=1;i<=m;i++){    p[i].x=read();p[i].y=read();p[i].a=read();p[i].b=read(); }}int main(){   T=read();pre();t=0;   while (T--){     init();t++;      printf("Case #%d: ",t);     if (cal()) puts("Yes");     else puts("No");       }}



0 0