給定一張n個頂點m條邊的無向圖(頂點編號為1,2,…,n),每條邊上帶有權值。所有權值都可以分解成2^a*3^b
的形式。現在有q個詢問,每次詢問給定四個引數u、v、a和b,請你求出是否存在一條頂點u到v之間的路徑,使得
路徑依次經過的邊上的權值的最小公倍數為2^a*3^b。注意:路徑可以不是簡單路徑。下面是一些可能有用的定義
:最小公倍數:k個數a1,a2,…,ak的最小公倍數是能被每個ai整除的最小正整數。路徑:路徑p:p1,p2,…,pk是頂
點序列,滿足對於任意1<=ii和pi+1之間都有邊相連。簡單路徑:如果路徑p:p1,p2,…,pk中,對於任意1
<=s≠t<=k都有ps≠pt,那麼稱路徑為簡單路徑。
輸入檔案的第一行包含兩個整數n和m,分別代表圖的頂點數和邊數。接下來m行,每行包含四個整數u、v、a、
b代表一條頂點u和v之間、權值為2^a*3^b的邊。接下來一行包含乙個整數q,代表詢問數。接下來q行,每行包含四
個整數u、v、a和b,代表一次詢問。詢問內容請參見問題描述。1<=n,q<=50000、1<=m<=100000、0<=a,b<=10^9
對於每次詢問,如果存在滿足條件的路徑,則輸出一行yes,否則輸出一行 no(注意:第乙個字母大寫,其餘
字母小寫) 。
4 5
1 2 1 3
1 3 1 2
1 4 2 1
2 4 3 2
3 4 2 2
5 1 4 3 3
4 2 2 3
1 3 2 2
2 3 2 2
1 3 4 4
yes
yes
yes
no no
考慮這樣一種暴力,對於每個詢問(u,v,a,b),將a<=a和b<=b的邊全部加入並查集中,最後判斷u和v是否在同一連通分量中且連通分量包含的最大的a=a,最大的b=b即可。
再考慮這樣一種暴力,把詢問和邊離線按a排序,詢問時在已經加入的邊中按b值排序加入並查集中。
那麼我們把這兩種暴力結合起來,按a值將詢問和邊分塊,前面的邊按第二種做法做,塊內的邊按第一種做法做就行了。
因為並查集需要支援撤銷,所以要用按秩合併,時間複雜度為o(nsqrt(n)logn)
#include#include#include#include#include#include#define rep(i,s,t) for(int i=s;i<=t;i++)#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int buffersize=1<<16;
char buffer[buffersize],*head,*tail;
inline char getchar()
return *head++;
}inline int read()
const int maxn=50010;
const int maxm=100010;
int n,m,q;
struct query
if(e[k].b<=t[j].b) merge(e[k].u,e[k].v,e[k].a,e[k].b);}}
else merge(t[j].u,t[j].v,t[j].a,t[j].b);}}
cnt=0;}}
rep(i,1,q) puts(ans[i]?"yes":"no");
return 0;
}
bzoj4537 HNOI2016 最小公倍數
time limit 40 sec memory limit 512 mb submit 563 solved 236 submit status discuss 給定一張n個頂點m條邊的無向圖 頂點編號為1,2,n 每條邊上帶有權值。所有權值都可以分解成2 a 3 b 的形式。現在有q個詢問,每次...
BZOJ4537 HNOI2016 最小公倍數
那個,事情是這樣的,從前有乙隻蒟蒻 對,就是我 然後有一天他心血來潮想創個部落格。可是沒過多久,他的熱情就過去了,甚至連一篇博文都沒有寫。然後,不知道怎麼了,他的部落格就被機房裡的dalao翻出來了,還被嘲諷了一番。於是他決定補救一下他的部落格。嗯,就這樣。這道題大概是這樣的。給定一張n個點m條邊的...
bzoj4537 Hnoi2016 最小公倍數
傳送門 思路 把邊按a排序,每sqrt m 分一組 然後把詢問按b排序,把在這組及以前的邊按b排序 把這些邊用並查集一條一條插入並維護 零散的部分暴力插入並記錄,做完後暴力撤銷 注意 並查集不能路徑壓縮,否則無法撤銷回去 include include include include include...