zoukankan      html  css  js  c++  java
  • [Luogu P5676][GZOI2017]小z玩游戏

    (GZOI2017D1T2)

    题目链接?不存在的 Luogu P5676 [GZOI2017]小z玩游戏

    题面

    做了半天一直不对,交一发就A了?样例出锅了吧。。(Luogu的样例是改过的,如果有错请联系我qwq)

    很显然对每个兴奋程度向能玩的游戏连边,游戏向相应的兴奋程度连边,然后问题转化为有多少游戏在一个环上,且能被兴奋程度为(1)的节点到达

    但是直接连边是(O(n^2))的,显然不行,需要优化。

    (N=100000)

    (N)个点(1sim N)表示当前兴奋程度

    (N)个点(N+1sim 2N)为中转节点

    (N)个点(2N+1sim 3N)表示(N)款游戏

    那么对于(1le i,jle N,i|j),连边((i,N+j)),表示兴奋程度(i)能玩有趣程度为(j)的游戏

    对于(1le ile n),连边((N+w_i,2N+i),(2N+i,e_i)),表示第(i)款游戏有趣程度为(w_i),玩完后兴奋程度变为(e_i)

    那么连边的复杂度就是喜闻乐见的调和级数:(sum_{i=1}^Nlimits frac Ni=O(Nlog N))

    接着跑一遍Tarjan,DFS一边求出哪些强连通分量可以被初始点达到

    然后判断一下就好了,注意大小为(1)的强连通分量不是环。

    时间复杂度 (O(TNlog N))

    空间复杂度 (O(Nlog N))

    代码:

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    
    inline int Min(const int a,const int b){return a<b?a:b;}
    inline int Max(const int a,const int b){return a>b?a:b;}
    #define Getchar (p1==p2&&(p2=(p1=In)+fread(In,1,1<<22,stdin),p1==p2)?EOF:*p1++)
    char In[1<<22],*p1=In,*p2=In,Ch;
    inline int Getint(int x=0)
    {
        while(!isdigit(Ch=Getchar));
        for(;isdigit(Ch);Ch=Getchar)x=x*10+(Ch^48);
        return x;
    }
    
    const int N=100000,V=N*3+5,E=N*14;
    int T,n,w[N+5],Ans;
    int Dfn[V],Low[V],Tim,Ins[V],Sta[V],Top;
    int Dcc[V],Siz[V],Dn,Deg[V],Vis[V];
    struct Graph
    {
        int Head[V],Next[E],To[E],En;
        inline void Clear(){memset(Head,En=0,sizeof Head);}
        inline void Add(int x,int y){Next[++En]=Head[x],To[Head[x]=En]=y;}
    }G1,G2;
    
    void Tarjan(int x)
    {
        Dfn[x]=Low[x]=++Tim,Ins[Sta[++Top]=x]=1;
        for(int i=G1.Head[x],y;i;i=G1.Next[i])
            if(!Dfn[y=G1.To[i]])Tarjan(y),Low[x]=Min(Low[x],Low[y]);
            else if(Ins[y])Low[x]=Min(Low[x],Dfn[y]);
        if(Low[x]==Dfn[x])
        {
            int y=++Dn;
            do Ins[y=Sta[Top--]]=0,Dcc[y]=Dn,++Siz[Dn];
            while(y!=x);
        }
    }
    
    void DFS(int x){if(!Vis[x]){Vis[x]=1;for(int i=G2.Head[x];i;i=G2.Next[i])DFS(G2.To[i]);}}
    
    int main()
    {
        freopen("in.txt","r",stdin);
        for(T=Getint();T--;printf("%d
    ",Ans))
        {
            G1.Clear(),G2.Clear(),n=Getint(),Ans=0;
            for(int i=1;i<=N;++i)
                for(int j=i;j<=N;j+=i)
                    G1.Add(i,N+j);
            for(int i=1;i<=n;++i)G1.Add(N+(w[i]=Getint()),N*2+i);
            for(int i=1;i<=n;++i)G1.Add(N*2+i,Getint());
            memset(Dfn,0,sizeof Dfn),memset(Siz,0,sizeof Siz),Tim=Dn=0;
            for(int i=1;i<=3*N;++i)if(!Dfn[i])Tarjan(i);
            memset(Deg,0,sizeof Deg),memset(Vis,0,sizeof Vis);
            for(int i=1,t;i<=3*N;++i)
                for(int j=G1.Head[i];j;j=G1.Next[j])
                    if(Dcc[i]!=(t=Dcc[G1.To[j]]))
                        G2.Add(Dcc[i],t),++Deg[t];
            DFS(Dcc[1]);
            for(int i=1;i<=n;++i)
                if(Vis[Dcc[N*2+i]]&&Siz[Dcc[N*2+i]]>1)
                    ++Ans;
        }
        return 0;
    }
    
  • 相关阅读:
    最大后验估计(MAP)
    mysql启动问题access denied for user 'root'@'localhost'(using password:YES)
    Median of Two Sorted Arrays-----LeetCode
    Two Sum-----LeetCode
    动态资源不缓存 filter
    过滤器 filter
    分页
    aop动态代理 事务 threadlocal
    ThreadLocal 开启事务
    数据库 元数据
  • 原文地址:https://www.cnblogs.com/LanrTabe/p/11896300.html
Copyright © 2011-2022 走看看