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

Sample Output

Case #1: Yes
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;
}
时间: 2024-10-14 23:12:54

4602: [Sdoi2016]齿轮的相关文章

bzoj 4602: [Sdoi2016]齿轮

传送门 题解: 一个简单的dfs或并查集即可搞定. dfs做法:建出图来以后,由一个节点跑一遍,如果儿子节点没有被遍历过,dfs此节点,否则,判断他俩的比例与他俩到根节点的比例之比是否相等. 对于判断两节点的比例,double可以安全存下. 我怕炸精度(其实不会,感觉自己跟个zz一样),于是想不用double,用个pair存下分子分母.后来觉得导起来太麻烦,于是用逆元求(越来越傻了). 逆元不需要太大的素数,大了会T,小了会WA. bzoj上测试了5个素数:1000000007,66191,73

[Sdoi2016]齿轮

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的齿轮也

【bzoj4602】[Sdoi2016]齿轮

dfs,连边,边权为比值,赋值搜索,遇到矛盾时退出 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> using namespace std; typedef long long LL; typedef double DB; #define eps 1e-8 #defin

[bzoj4602] [Sdoi2016]齿轮

记忆化搜索,强行double可过...数据简直.. 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<cstdlib> 6 #define ld double 7 using namespace std; 8 const int maxn=1023,maxm=10023; 9 const ld eps=1e-8; 10

BZOJ4602: [Sdoi2016]齿轮 DFS 逆元

这道题就是一个DFS,有一篇奶牛题几乎一样.但是这道题卡精度. 这道题网上的另一篇题解是有问题的.取对数这种方法可以被轻松卡.比如1e18 与 (1e9-1)*(1e9+1)取对数根本无法保证不被卡精度.所以我们需要换一个方法. 我们取一个大质数,在这个质数的模意义下进行运算:乘法是乘法,除法变成乘逆元,负数加一个质数.这种方法虽然可能冲突,但是与数据无关. #include<cstdio> using namespace std ; struct edge { int p ; int a ;

待 题表

题表 达哥终极杂题表Bzoj2839 hdu6021 Codeforces 804DBzoj2248 hdu5575 Codeforces 786CBzoj2013 bzoj2676 Codeforces 803CBzoj2386 bzoj3782 Codeforces 813DBzoj2699 cogs1667 Codeforces 814DBzoj4798 bzoj2064 Codeforces 814EBzoj4639 bzoj3505 Codeforces 815ABzoj4417 bz

联赛之前的题表(已完成)汇总(可能有遗漏)

联赛之前的搞搞(其实是懒得分类) 博弈论 poj3537 poj1704 hdu5996两个插头 HDU1693 Eat the Trees COGS1283. [HNOI2004] 邮递员kdtree板子1941: [Sdoi2010]Hide and Seek旋转卡壳 pj2187凸包 cogs896 bzoj2829 信用卡凸包莫比乌斯反演基础 bzoj 4173 zhao gui lv bzoj 3529 mobiwus bzoj 4407 mobiwus bzoj 2818 mobiw

[qbzt寒假] 并查集

并查集: \(Kruscal\),\(Tarjan\)求\(LCA\) 分类并查集:食物链,团伙(敌人的敌人是我的朋友) 带权并查集:\(SDOI2016\)齿轮(可用 int father(int x) { return fa[x]==x?x:fa[x]=father(f[x]); } Luogu3101 滑雪等级[] 建边:任意相邻两格子之间建边,权值为海拔差 将边排序,从小往大一个一个往里加,当一个并查集内部有起点,并且大小(点数)>=T,这里面所有的起点的D=最后加入的边 #includ

BZOJ 4517: [Sdoi2016]排列计数 错排+逆元

4517: [Sdoi2016]排列计数 Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m 个数是稳定的 满足条件的序列可能很多,序列数对 10^9+7 取模. Input 第一行一个数 T,表示有 T 组数据. 接下来 T 行,每行两个整数 n.m. T=500000,n≤1000000,m≤1000000 Output 输出 T 行,每行一个数,表示