1. 程式人生 > >【BZOJ4602】齒輪,帶權並查集

【BZOJ4602】齒輪,帶權並查集

Time:2016.06.09
Author:xiaoyimi
轉載註明出處謝謝

傳送門
Ps
這段時間在狂補文化課,10天就碰過一次鍵盤,結果回來發現連快速讀入都敲不對了233
接下來一段時間仍保持這種狀態了……
思路:
R2唯一可做的一道題?
在學校弄了個30分做法
回來一交A了……
感覺分解質因數的方法高大上啊有木有
sum[x]表示x是其所在集合的代表元素fa[x]的幾分之幾(所以sum[fa[x]]=1,如果W[fa[x]]W[x]=AB,那麼sum[x]=BA
詢問判斷:如果u,v在同一集合裡直接判斷即可,反之將兩者合併
合併思路:如果我們要合併u,v兩個元素所在集合且u

v=xy,那麼我們需要解決的就是fa[u],fa[v]之間的數量關係,讓sum[fa[u]]=sum[v]xsum[u]y即可
find操作:先讓fa[x]合併到一個新集合裡,這時sum[fa[x]]已經更新過了,只要讓sum[x]=sum[x]sum[fa[x]]就行了
(以上一些式子的推導很簡單,我就不列過程了)
注意:
暫無
程式碼:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int T,n,m;
int
fa[1003]; double sum[1003]; int in() { int t=0;char ch=getchar();bool f=0; while (ch>'9'||ch<'0') f=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') t=(t<<1)+(t<<3)+ch-48,ch=getchar(); return f?-t:t; } int find(int x) { if (x==fa[x]) return x; int t=fa[x]; fa[x]=find(t); sum[x]*=sum[t]; return
fa[x]; } void work() { n=in();m=in(); for (int i=1;i<=n;i++) fa[i]=i,sum[i]=1; int x,y,u,v;bool flag=0; while (m--) { u=in();v=in();x=in();y=in(); int f1=find(u),f2=find(v); if (f1==f2) if (fabs(sum[u]/sum[v]-1.0*x/y)>1e-9) flag=1; else; else fa[f1]=f2, sum[f1]=sum[v]*x/(sum[u]*y); } if (flag) puts("No"); else puts("Yes"); } main() { T=in(); for (int i=1;i<=T;i++) printf("Case #%d: ",i),work(); }