Description

  给定一张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<=i<k,节点Pi和Pi+1之间都有边相连。简单路径:如果路径P:P1,P2,…,Pk中,对于任意1
<=s≠t<=k都有Ps≠Pt,那么称路径为简单路径。

Input

  输入文件的第一行包含两个整数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

Output

  对于每次询问,如果存在满足条件的路径,则输出一行Yes,否则输出一行 No(注意:第一个字母大写,其余
字母小写) 。

Sample Input

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

Sample Output

Yes
Yes
Yes
No
No

题解:

http://blog.csdn.net/thy_asdf/article/details/51203421

注意并查集不能路径压缩,要用启发式合并

code:

 #include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
char ch;
bool ok;
void read(int &x){
for (ok=,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=;
for (x=;isdigit(ch);x=x*+ch-'',ch=getchar());
if (ok) x=-x;
}
const int maxn=;
int n,m,q,rm,tot,cnt,fa[maxn],siz[maxn],maxa[maxn],maxb[maxn];
int find(int x){return x==fa[x]?x:find(fa[x]);}
bool ans[maxn];
struct Data{
int u,v,a,b,id;
void init(int i){read(u),read(v),read(a),read(b),id=i;}
}edge[maxn],quer[maxn],tmp[maxn];
bool cmpa(const Data &x,const Data &y){return x.a<y.a||(x.a==y.a&&x.b<y.b);}
bool cmpb(const Data &x,const Data &y){return x.b<y.b||(x.b==y.b&&x.a<y.a);}
struct Oper{
int u,v,fa,siz,ma,mb;
}oper[maxn];
void merge(int u,int v,int a,int b){
u=find(u),v=find(v);
if (siz[u]>siz[v]) swap(u,v);
oper[++cnt]=(Oper){u,v,fa[u],siz[v],maxa[v],maxb[v]};
if (u==v) maxa[u]=max(maxa[u],a),maxb[u]=max(maxb[u],b);
else fa[u]=v,siz[v]+=siz[u],maxa[v]=max(maxa[v],max(maxa[u],a)),maxb[v]=max(maxb[v],max(maxb[u],b));
}
void undo(){
for (;cnt;cnt--){
fa[oper[cnt].u]=oper[cnt].fa;
maxa[oper[cnt].v]=oper[cnt].ma;
maxb[oper[cnt].v]=oper[cnt].mb;
siz[oper[cnt].v]=oper[cnt].siz;
}
}
int main(){
read(n),read(m),rm=sqrt(m);
for (int i=;i<=m;i++) edge[i].init(i);
sort(edge+,edge+m+,cmpa);
read(q);
for (int i=;i<=q;i++) quer[i].init(i);
sort(quer+,quer+q+,cmpb);
for (int i=;i<=m;i+=rm){
tot=;
for (int j=;j<=q;j++) if (edge[i].a<=quer[j].a&&(i+rm>m||quer[j].a<edge[i+rm].a)) tmp[++tot]=quer[j];
sort(edge+,edge+i,cmpb);
for (int j=;j<=n;j++) fa[j]=j,siz[j]=,maxa[j]=maxb[j]=-;
for (int j=,k=;j<=tot;j++){
for (;k<i&&edge[k].b<=tmp[j].b;k++) merge(edge[k].u,edge[k].v,edge[k].a,edge[k].b);
cnt=;
for (int p=i;p<i+rm&&p<=m;p++) if (edge[p].a<=tmp[j].a&&edge[p].b<=tmp[j].b)
merge(edge[p].u,edge[p].v,edge[p].a,edge[p].b);
int x=find(tmp[j].u),y=find(tmp[j].v);
ans[tmp[j].id]=(x==y&&maxa[x]==tmp[j].a&&maxb[x]==tmp[j].b);
undo();
}
}
for (int i=;i<=q;i++) if (ans[i]) puts("Yes"); else puts("No");
return ;
}

4537: [Hnoi2016]最小公倍数的更多相关文章

  1. BZOJ 4537: [Hnoi2016]最小公倍数 [偏序关系 分块]

    4537: [Hnoi2016]最小公倍数 题意:一张边权无向图,多组询问u和v之间有没有一条a最大为a',b最大为b'的路径(不一定是简单路径) 首先想到暴力做法,题目要求就是判断u和v连通,并查集 ...

  2. bzoj 4537 HNOI2016 最小公倍数

    Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,-,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在有q个询问,每次询问给定四个参数u.v.a和b,请你 ...

  3. bzoj 4537: [Hnoi2016]最小公倍数 分块+并查集

    题目大意: 给定一张n个点m条边的无向图,每条边有两种权.每次询问某两个点之间是否存在一条路径上的边的两种权的最大值分别等于给定值. n,q <= 50000. m <= 100000 题 ...

  4. [BZOJ4537][HNOI2016]最小公倍数(分块+并查集)

    4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1687  Solved: 607[Submit][Stat ...

  5. [BZOJ4537][Hnoi2016]最小公倍数 奇怪的分块+可撤销并查集

    4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1474  Solved: 521[Submit][Stat ...

  6. 【LG3247】[HNOI2016]最小公倍数

    [LG3247][HNOI2016]最小公倍数 题面 洛谷 题解 50pts 因为拼凑起来的部分分比较多,所以就放一起了. 以下设询问的\(a,b\)为\(A,B\), 复杂度\(O(nm)\)的:将 ...

  7. 【BZOJ4537】[Hnoi2016]最小公倍数 分块

    [BZOJ4537][Hnoi2016]最小公倍数 Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,…,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在 ...

  8. [HNOI2016]最小公倍数

    题目描述 给定一张N个顶点M条边的无向图(顶点编号为1,2,...,n),每条边上带有权值.所有权值都可以分解成2a∗3b2^a*3^b2a∗3b 的形式. 现在有q个询问,每次询问给定四个参数u.v ...

  9. 洛谷P3247 [HNOI2016]最小公倍数 [分块,并查集]

    洛谷 思路 显然,为了达到这个最小公倍数,只能走\(a,b\)不是很大的边. 即,当前询问的是\(A,B\),那么我们只能走\(a\leq A,b\leq B\)的边. 然而,为了达到这最小公倍数,又 ...

随机推荐

  1. PostgreSQL9.5 新特性

    PostgreSQL9.5 新特性 PostgreSQL9.5:Foreign Table Inheritance PostgreSQL9.5:Row-Level Security Policies ...

  2. 转 python 之 分割参数getopt

    python 之 分割参数getopt os下有个方法walk,非常的好用,用来生成一个generator.每次可以得到一个三元tupple,其中第一个为起始路径,第二个为起始路径下的文件夹,第三个是 ...

  3. Java实现邮箱找回密码

    通过邮件找回密码功能的实现 1.最近开发一个系统,有个需求就是,忘记密码后通过邮箱找回.现在的系统在注册的时候都会强制输入邮箱,其一目的就是 通过邮件绑定找回,可以进行密码找回.通过java发送邮件的 ...

  4. 自定义toast功能

    http://download.csdn.net/detail/caryt/8105031

  5. BZOJ 2754([SCOI2012]喵喵叫的星球-统计序列的后缀阵列中子序列出现次数)

    2754: [SCOI2012]喵喵叫的星球 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 805  Solved: 380 [id=2754&qu ...

  6. End-to-End Tracing of Ajax/Java Applications Using DTrace

    End-to-End Tracing of Ajax/Java Applications Using DTrace         By Amit Hurvitz, July 2007     Aja ...

  7. 文件MD5查看器工具与源码实现及下载

    由于工作中经常需要查看文件的MD5值,先前网上找了几个MD5值查看工具,但基本都是选择文件,还没有复制功能,于是今天我就自己编写了个MD5查看工具,支持文件拖拽查看,并可以复制功能. 由于本工具比较小 ...

  8. Java基础知识强化之集合框架笔记48:产生10个1~20之间的随机数(要求:随机数不能重复) 简洁版

    1. 编写一个程序,获取10个1至20的随机数,要求随机数不能重复. 分析:  A: 创建随机数对象  B: 创建一个HashSet集合  C: 判断集合的长度是不是小于10    是:就创建一个随机 ...

  9. 必应代码搜索 Bing Code Search 安装

    微软这几天推出基于bing搜索引擎的  Bing Code Search ,可直接在浏览器上搜索和运行代码.目前中文版必应无法使用本功能,有需要的同学可以转到英文版进行搜索: 英文版必应:  http ...

  10. Linux查看某个文件被哪些进程PID占用

    比如查看test.sh这个文件被哪些进程占用,可以用: lsof | grep test.sh 或者 fuser -v test.sh