• 【bzoj4602】[Sdoi2016]齿轮 BFS


    题目描述

    给出一张n个点m条边的有向图,每条边 (u,v,x,y) 描述了 u 的点权乘 x 等于 v 的点权乘 y (点权可以为负)。问:是否存在满足条件的图。

    输入

    有多组数据,第一行给定整数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

    输出

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

    样例输入

    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

    样例输出

    Case #1: Yes
    Case #2: No


    题解

    BFS

    显然固定一个点,通过条件判断出其它点是否是它的固定倍数即可。添加双向边,维护每个点是某个点的多少倍,BFS验证。

    但是有一个问题:倍数关系是指数级的,因此需要取对数。

    但是有一个问题:边权有负数,因此需要维护符号和绝对值的对数。

    但是有一个问题:有精度误差,因此需要设eps为$10^{-6}$。

    时间复杂度$O(T(n+m))$

    #include <queue>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #define N 1010
    #define M 20010
    using namespace std;
    queue<int> q;
    int head[N] , to[M] , vp[M] , next[M] , cnt , vis[N] , flag[N];
    double val[M] , dis[N];
    void add(int x , int y , double z , int p)
    {
    	to[++cnt] = y , val[cnt] = z , vp[cnt] = p , next[cnt] = head[x] , head[x] = cnt;
    }
    bool judge(int p)
    {
    	int i , x;
    	while(!q.empty()) q.pop();
    	vis[p] = 1 , q.push(p);
    	while(!q.empty())
    	{
    		x = q.front() , q.pop();
    		for(i = head[x] ; i ; i = next[i])
    		{
    			if(!vis[to[i]]) vis[to[i]] = 1 , flag[to[i]] = flag[x] ^ vp[i] , dis[to[i]] = dis[x] + val[i] , q.push(to[i]);
    			else if(flag[to[i]] != (flag[x] ^ vp[i]) || fabs(dis[to[i]] - dis[x] - val[i]) > 1e-6) return 0;
    		}
    	}
    	return 1;
    }
    int main()
    {
    	int T , Case;
    	scanf("%d" , &T);
    	for(Case = 1 ; Case <= T ; Case ++ )
    	{
    		memset(head , 0 , sizeof(head)) , memset(vis , 0 , sizeof(vis)) , cnt = 0;
    		int n , m , x , y , i , a , b;
    		scanf("%d%d" , &n , &m);
    		while(m -- )
    		{
    			scanf("%d%d%d%d" , &x , &y , &a , &b);
    			if(b > 0) add(x , y , log(b) - log(a) , 0) , add(y , x , log(a) - log(b) , 0);
    			else add(x , y , log(-b) - log(a) , 1) , add(y , x , log(a) - log(-b) , 1);
    		}
    		for(i = 1 ; i <= n ; i ++ )
    			if(!vis[i])
    				if(!judge(i))
    					break;
    		printf("Case #%d: " , Case);
    		if(i > n) puts("Yes");
    		else puts("No");
    	}
    	return 0;
    }
    

     

  • 相关阅读:
    TWebBrowser 与 MSHTML(3): window 对象的属性、方法、事件纵览
    使 SaveDialog 对话框的文件名选择变灰 回复 "delphan" 的问题
    [最新通知]今日17:0019:00将不能访问博客园
    编辑器改进(三)
    博客园.Text技术支持移至PSP技术支持中心
    [公告]关于投稿到Dearbook的“读书笔记”专栏
    [致歉]博客园服务器停运时间超出计划时间
    [博客园公告]给发表评论增加了验证码功能
    CS Beta 1发布了
    [通知]11月6日(星期六)可能不能访问博客园
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7764850.html
Copyright © 2020-2023  润新知