• LG P3247 [HNOI2016]最小公倍数


    Description

    给定一张N个顶点M条边的无向图(顶点编号为1,2,...,n),每条边上带有权值。所有权值都可以分解成$2^a*3^b$的形式。

    现在有q个询问,每次询问给定四个参数u、v、a和b,请你求出是否存在一条顶点u到v之间的路径,使得路径依次经过的边上的权值的最小公倍数为$2^a*3^b$。

    注意:路径可以不是简单路径。

    下面是一些可能有用的定义,如果与其它地方定义不同,在本题中以下面的定义为准:

    最小公倍数: $ k $ 个数 $ a_1 , a_2, ldots, a_k $ 的最小公倍数是能被每个 $a_i$ 整除的最小正整数。

    路径:顶点序列 $ P colon P_1,P_2,ldots,P_k $ 是一条路径,当且仅当 $k geq 2$,且对于任意 $ 1 leq i < k $ ,节点 $ P_i $ 和 $ P_{i+1} $ 之间都有边相连。

    简单路径:如果路径 $ P colon P_1,P_2,ldots,P_k $ 中,对于任意 $ 1 leq s eq t leq k $ 都有 $ P_s eq P_t $ ,那么称 $P$ 为简单路径。

    Solution

    有用的边两种权值都不超过询问,所以对于每次询问只需要将权值小于等于询问的边加入即可

    先对a权值排序,进行分块

    将每个询问挂在块上保证之前的块的a都小于等于询问

    每次处理一个块时,询问和边集对b排序,零散部分暴力加入

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<stack>
    #include<queue>
    #include<cmath>
    using namespace std;
    int n,m,Q,B,siz,fa[50005],maxa[50005],maxb[50005],ans[50005];
    bool vst[50005],vis[50005];
    struct Node{
        int to,a,b;
    };
    struct Edge{
        int u,v,a,b,id;
    }edge[100005],que[50005];
    vector<Node>ve[50005];
    vector<Edge>qu[1005];
    stack<int>sta;
    queue<int>q;
    inline int read(){
        int w=0,f=1;
        char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
        return w*f;
    }
    bool cmp1(Edge x,Edge y){return x.a<y.a;}
    bool cmp2(Edge x,Edge y){return x.b<y.b;}
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    int main(){
        n=read(),m=read();
        for(int i=1;i<=m;i++)edge[i]=(Edge){read(),read(),read(),read(),0};
        Q=read();
        for(int i=1;i<=Q;i++)que[i]=(Edge){read(),read(),read(),read(),i};
        sort(edge+1,edge+m+1,cmp1),sort(que+1,que+Q+1,cmp1),siz=1.5*m/sqrt(Q),B=(m+siz-1)/siz;
        int pos=1;
        for(int i=1;i<=Q;i++){
            while(que[i].a>=edge[min(pos*siz,m)].a&&pos<B)++pos;
            qu[pos].push_back(que[i]);
        }
        for(int i=1;i<=B;i++){
            int p=1;
            for(int j=1;j<=n;j++)fa[j]=j;
            memset(maxa,-1,sizeof(maxa)),memset(maxb,-1,sizeof(maxb)),sort(edge+1,edge+(i-1)*siz+1,cmp2),sort(qu[i].begin(),qu[i].end(),cmp2);
            for(int j=0;j<qu[i].size();j++){
                while(p<=(i-1)*siz&&qu[i][j].b>=edge[p].b){
                    int fx=find(edge[p].u),fy=find(edge[p].v);
                    if(fx>fy)swap(fx,fy);
                    maxa[fx]=max(maxa[fx],max(maxa[fy],edge[p].a)),maxb[fx]=max(maxb[fx],max(maxb[fy],edge[p].b)),fa[fy]=fx,++p;
                }
                for(int k=(i-1)*siz+1;k<=i*siz&&k<=m;k++)if(edge[k].a<=qu[i][j].a&&edge[k].b<=qu[i][j].b){
                    int u=find(edge[k].u),v=find(edge[k].v);
                    if(!vst[u])vst[u]=true,sta.push(u);
                    if(!vst[v])vst[v]=true,sta.push(v);
                    ve[u].push_back((Node){v,edge[k].a,edge[k].b}),ve[v].push_back((Node){u,edge[k].a,edge[k].b});
                }
                int u=find(qu[i][j].u),v=find(qu[i][j].v),taga=-1,tagb=-1;
                if(!vst[u])vst[u]=true,sta.push(u);
                if(!vst[v])vst[v]=true,sta.push(v);
                q.push(u),vis[u]=true;
                while(q.size()){
                    int u=q.front();
                    q.pop(),taga=max(taga,maxa[u]),tagb=max(tagb,maxb[u]);
                    for(int k=0;k<ve[u].size();k++){
                        taga=max(taga,ve[u][k].a),tagb=max(tagb,ve[u][k].b);
                        if(!vis[ve[u][k].to])vis[ve[u][k].to]=true,q.push(ve[u][k].to);
                    }
                }
                ans[qu[i][j].id]=(vis[v]&&taga==qu[i][j].a&&tagb==qu[i][j].b);
                while(sta.size())ve[sta.top()].clear(),vst[sta.top()]=vis[sta.top()]=false,sta.pop();
            }
        }
        for(int i=1;i<=Q;i++)puts(ans[i]?"Yes":"No");
        return 0;
    }
    [HNOI2016]最小公倍数
  • 相关阅读:
    Asp.net Json 解析 与 直接用ip访问返回josn
    mysql 时间函数
    Android之TelephonyManager类的使用案例
    android:screenOrientation的说明 固定屏幕显示方向
    在android.app.Application中定义全局变量
    Android开发实例详解之IMF(Android SDK Sample—SoftKeyboard)
    Android InputMethodManager输入法简介
    android ImageView的属性android:scaleType,即ImageView.setScaleType(ImageView.ScaleType)
    VS编译常见错误枚举01
    Visual C++ Samples-------------Code Project
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14253600.html
Copyright © 2020-2023  润新知