传送门
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
By AHdoc命题 鸣谢Loi_DQS上传
题解
奇怪的并查集,然而为什么跑的这么慢QAQ
也许是用了long long的缘故,然而并没有办法
CODE:
#include<cstdio>
typedef long long ll;
int f[1005];
ll rotate[1005][2];
bool same[1005];
int T,n,m,x,y;
ll u,v;
bool ans;
inline ll abs(ll n){if(n<0)return -n;return n;}
ll gcd(ll a,ll b)
{
if(!b) return a;
return gcd(b,a%b);
}
inline ll lcm(ll a,ll b)
{
return a*b/gcd(a,b);
}
int find(int n)
{
if(f[n]!=n)
{
int tmp=find(f[n]);
if(same[n]==same[f[n]]) same[n]=1;
else same[n]=0;
ll T=lcm(rotate[n][1],rotate[f[n]][0]);
rotate[n][0]*=T/rotate[n][1];
rotate[n][1]=rotate[f[n]][1]*T/rotate[f[n]][0];
T=gcd(rotate[n][0],rotate[n][1]);
rotate[n][0]/=T,rotate[n][1]/=T;
f[n]=tmp;
}
return f[n];
}
inline bool merge(int x,int y,ll u,ll v)
{
int xx=find(x),yy=find(y);
ll tmp=lcm(u,lcm(abs(v),lcm(rotate[x][0],lcm(rotate[x][1],lcm(rotate[y][0],rotate[y][1])))));
u*=tmp,v*=tmp;
u/=rotate[x][0],u*=rotate[x][1];
v/=rotate[y][0],v*=rotate[y][1];
tmp=gcd(u,abs(v));
u/=tmp,v/=tmp;
int t=1;
if(!same[x]) t^=1;
if(!same[y]) t^=1;
if(v<0) t^=1,v=-v;
if(xx!=yy)
{
if(!t) same[yy]=0;
rotate[yy][0]=v,rotate[yy][1]=u;
f[yy]=xx;
return 1;
}
if(!t==same[yy]||rotate[yy][0]!=v||rotate[yy][1]!=u) return 0;
return 1;
}
int main()
{
scanf("%d",&T);
for(int k=1;k<=T;k++)
{
scanf("%d%d",&n,&m);
ans=1;
for(int i=1;i<=n;i++)
f[i]=i,rotate[i][0]=rotate[i][1]=same[i]=1;
for(int i=1;i<=m;i++)
{
scanf("%d%d%lld%lld",&x,&y,&u,&v);
ll tmp=gcd(u,abs(v));
u/=tmp,v/=tmp;
if(ans&&!merge(x,y,u,v)) ans=0;
}
if(ans) printf("Case #%d: Yes\n",k);
else printf("Case #%d: No\n",k);
}
return 0;
}