1. 程式人生 > >[SDOI2016] BZOJ4602 齒輪-dfs-帶權並查集-數論逆元-質因數分解

[SDOI2016] BZOJ4602 齒輪-dfs-帶權並查集-數論逆元-質因數分解

傳送門

題解:

總結幾種做法,並指出其中的優劣;

主要是兩種演算法,一種是暴力dfs,另一種是並查集。

事實上這種“每條邊都考慮”大概都可以用上述兩種辦法處理,並查集複雜度略高,但是其實近乎線性。

暴力dfs就是,建一張無向圖(不能是有向的),然後對於每個聯通塊,第一個元素設為1,然後通過第一個元素,

算出其它元素的值,然後對於點x,以及邊(x,y),如果y也訪問過了,就判斷一下通過x算的y和已經算出來的y是否相等即可。

並查集是類似的,因為是無向圖,先加邊加成樹(或者森林),然後之後在加邊就判斷即可。

其實這題最主要的是精度問題。

但是出題人特別良心沒有卡精度,double都水過去了。

精度控制的幾種辦法:

第一種,最好想的,直接上double(或者long double)。

問題:資料理論最大是100^1000的,理論上會爆(事實沒有)。

第二種,比較容易想到的,取對數,變成加減運算。

問題:可以卡精度,例如1e18和(1e9-1)*(1e9+1)。但是也沒有卡。

第三種,在模質數意義下進行運算,除法變成乘逆元,判斷類似雜湊。

問題:理論上會衝突,實際上不會(幾乎不會)。

第四種,注意到x,y<=100可以質因數分解。

問題:這個應該能夠保證正確,但是常數略大,(儘管對於這個題是足夠的)。

程式碼:用的是第一種SB方法竟然沒有被卡QwQ

//BZOJ 4602
//SDOI 2016
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define MAXN 1100
#define MAXM 21000
using namespace std;
struct edges{
	int to,pre;
	double wgt;
}e[MAXM];
int h[MAXN],etop;
int add_edge(int u,int v,double wgt)
{
	etop++;
	e[etop].to=v;
	e[etop].pre=h[u];
	e[etop].wgt=wgt;
	h[u]=etop;
	return 0;
}
double val[MAXN];
const double ep=0.000001;
bool vis[MAXN];
bool dcmp(double x)
{
	if(fabs(x)<ep) return false;
	else return true;
}
bool dfs(int x)
{
	vis[x]=true;
	for(int i=h[x];i;i=e[i].pre)
		if(!vis[e[i].to])
		{
			val[e[i].to]=val[x]*e[i].wgt;
			if(!dfs(e[i].to)) return false;
		}
		else if(dcmp(val[e[i].to]-val[x]*e[i].wgt)) return false;
	return true;
}
int main()
{
	int T;scanf("%d",&T);
	for(int t=1;t<=T;t++)
	{
		int n,m;scanf("%d%d",&n,&m);
		memset(h,0,sizeof(h));etop=0;
		memset(vis,false,sizeof(vis));
		for(int i=1;i<=m;i++)
		{
			int u,v,x,y;scanf("%d%d%d%d",&u,&v,&x,&y);
			add_edge(u,v,(double)y/x);
			add_edge(v,u,(double)x/y);
		}
		for(int i=1;i<=n;i++)
			if(!vis[i])
			{
				val[i]=1.0;
				if(!dfs(i))
				{
					printf("Case #%d: No\n",t);
					goto loop;
				}
			}
		printf("Case #%d: Yes\n",t);
		loop:;
	}
	return 0;
}


相關推薦

[SDOI2016] BZOJ4602 齒輪-dfs--數論-質因數分解

傳送門 題解: 總結幾種做法,並指出其中的優劣; 主要是兩種演算法,一種是暴力dfs,另一種是並查集。 事實上這種“每條邊都考慮”大概都可以用上述兩種辦法處理,並查集複雜度略高,但是其實近乎線性。 暴力dfs就是,建一張無向圖(不能是有向的),然後對於每個聯通塊,第一個元素

BZOJ4602 Sdoi2016 齒輪】*

BZOJ4602 Sdoi2016 齒輪 Description 現有一個傳動系統,包含了N個組合齒輪和M個鏈條。每一個鏈條連線了兩個組合齒輪u和v,並提供了一個傳動比x : y。即如果只考慮這兩個組合齒輪,編號為u的齒輪轉動x圈,編號為v的齒輪會轉動y圈。傳

BZOJ4602齒輪

Time:2016.06.09 Author:xiaoyimi 轉載註明出處謝謝 傳送門 Ps 這段時間在狂補文化課,10天就碰過一次鍵盤,結果回來發現連快速讀入都敲不對了233 接下

齒輪[好題]

傳送門 我們發現如果a與b的轉比為k1 , b與c的轉比為k2 , 那麼a與c的轉比為 k1*k2 我們並查集判連通性時 , 順便維護一個dis , dis[x]表示dis與rt的轉比 維護dis時 , 每次都乘上fa的dis就可以了 , 注意dis初始值為1 當出現環時 , 如果u

poj 1182 ()

ios int 查找 食物 spa script ble 距離 輸出 食物鏈 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 71361 Accepted: 21131 Des

HDU3635 Dragon Balls(

align size any cat webkit city ret follow num 題目鏈接:   http://acm.hdu.edu.cn/showproblem.php?pid=3635 題目描述: Dragon Balls Problem Descript

HDU 3635 Dragon Balls()

clas pos 水題 ont span popu post join -- 題目地址:pid=3635">HDU 3635 加權並查集水題。 用num數組維護該城市有多少龍珠,用times數組維護每一個龍珠運輸了多少次。num數組在合並的時候維護。times數

】HDU 3047 Zjnu Stadium

void mem ios ack string blank iostream style csdn http://acm.hdu.edu.cn/showproblem.php?pid=3047 【題意】 http://blog.csdn.net/hj1107402232/a

——poj2236(

algorithm blog oid poj2236 stream 命令 net 最大 spa 題目:Wireless Network 題意:給定n臺已損壞計算機的位置和計算機最遠通信距離d,然後分別根據命令執行以下兩種操作: "O p" (1 <= p <=

HDU - 3038 / 3048 () (待補)

hdu return bsp value 題目 ios i++ mes sca 題目鏈接:點我點我 題意: 題解: 兩題代碼差不多,放個3047的。 1 #include <cstdio> 2 #include <iostream>

D - How Many Answers Are Wrong HDU - 3038

following follow tar ndt wrong get gin k60 man w2csi眾美8uk唾嚎http://www.facebolw.com/space/2103369/following Y47炮K兌B巧約鐐39http://www.facebo

【BZOJ 3376】[Usaco2004 Open]Cube Stacking 方塊遊戲

inline 記錄 cst cnblogs bsp tac bzoj 開始 scan 這道題一開始以為是平衡樹結果發現復雜度過不去,然後發現我們一直合並而且只是記錄到最低的距離,那麽就是帶權並查集了,帶權並查集的權一般是到根的距離,因為不算根要好打,不過還有一些其他的,具體

HDU 3038 How Many Answers Are Wrong(

define pro tor memset set sizeof fin printf class 題目鏈接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1272 題目大意:有n條信息,每條信息都給出區間l到r的值,如果

POJ 1182 食物鏈 (

動物 return i++ rip width d+ oid body 思維 食物鏈 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 78551 Accepte

poj1703 Find them, Catch them(

har find 輸出 scanf -- oot n) puts stdin 題目鏈接 http://poj.org/problem?id=1703 題意 有兩個幫派:龍幫和蛇幫,兩個幫派共有n個人(編號1~n),輸入m組數據,每組數據為D [a][b]或A [a][

poj2492 A Bug's Life(

tab set 復雜 鏈接 image 之間 判斷 clu 成了 題目鏈接 http://poj.org/problem?id=2492 題意 蟲子有兩種性別,有n只蟲子,編號1~n,輸入m組數據,每組數據包含a、b兩只蟲子,表示a、b為不同性別的蟲子,根據輸入的m組

poj1182 食物鏈(

txt amp 帶權並查集 htm 代碼 || blog 參考 oid 題目鏈接 http://poj.org/problem?id=1182 思路 前面做的帶權並查集的權值記錄該結點與其父結點是否是同一類,只有兩種取值情況(0,1),在這題中某結點a和其父結點b的取

POJ 1988 Cube Stacking (

ons from += same file rep stream scribe 並查集 Farmer John and Betsy are playing a game with N (1 <= N <= 30,000)identical cubes label

HihoCoder - 1515 分數調查 (

amp code space blog contain script += esp 判斷 小Hi的學校總共有N名學生,編號1-N。學校剛剛進行了一場全校的古詩文水平測驗。 學校沒有公布測驗的成績,所以小Hi只能得到一些小道消息,例如X號同學的分數比Y號同學的分數高S分

poj2492A Bug's Life——

sce oot poj turn cst tin 判斷 name .org 題目:http://poj.org/problem?id=2492 所有元素加入同一個並查集中,通過其偏移量%2將其分類為同性與異性,據此判斷事件。 代碼如下: #include<iostr