• BZOJ5109 CodePlus 2017大吉大利,晚上吃鸡!(最短路+拓扑排序+bitset)


      首先跑正反两遍dij求由起点/终点到某点的最短路条数,这样条件一就转化为f(S,A)*f(T,A)+f(S,B)*f(T,B)=f(S,T)。同时建出最短路DAG,这样图中任何一条S到T的路径都是最短路径,对于条件二就只需要判断A是否能走到B。注意到空间开的非常大。那么对于条件二的可达性显然是可以bitset优化的。对于条件一可以map套bitset。两者and再count一下就可以了。bzoj的空间限制开小了于是这种做法就直接MLE了。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<bitset> 
    using namespace std;
    #define ll long long
    #define N 50010
    #define P 1000000007
    char getc(){char c=getchar();while (c==10||c==13||c==32) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,S,T,t,p[N],f[2][N],g[N];
    ll d[2][N];
    bool flag[N];
    struct data{int to,nxt,len;
    }edge[N<<1];
    struct data2
    {
        int x;ll d;
        bool operator <(const data2&a) const
        {
            return d>a.d;
        }
    };
    priority_queue<data2> q;
    bitset<N> to[N],from[N];
    map<int,bitset<N> > cnt;
    void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
    void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
    void dijkstra(int S,int op)
    {
        memset(d[op],42,sizeof(d[op]));d[op][S]=0;f[op][S]=1;
        memset(flag,0,sizeof(flag));
        while (!q.empty()) q.pop();
        q.push((data2){S,0});
        for (;;)
        {
            while (!q.empty()&&flag[q.top().x]) q.pop();
            if (q.empty()) break;
            data2 x=q.top();q.pop();
            flag[x.x]=1;
            for (int i=p[x.x];i;i=edge[i].nxt)
            {
                if (x.d+edge[i].len<d[op][edge[i].to])
                {
                    d[op][edge[i].to]=x.d+edge[i].len;
                    q.push((data2){edge[i].to,d[op][edge[i].to]});
                    f[op][edge[i].to]=0;
                }
                if (x.d+edge[i].len==d[op][edge[i].to])
                inc(f[op][edge[i].to],f[op][x.x]);
            }
        }
    }
    namespace shortestpathDAG
    {
        int p[N]={0},q[N]={0},degree[N]={0},t=0;
        struct data{int to,nxt;}edge[N];
        void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
        void topsort()
        {
            for (int i=1;i<=t;i++) degree[edge[i].to]++;
            int head=0,tail=0;for (int i=1;i<=n;i++) if (!degree[i]) q[++tail]=i;
            while (tail<n)
            {
                int x=q[++head];
                for (int i=p[x];i;i=edge[i].nxt)
                {
                    degree[edge[i].to]--;
                    if (!degree[edge[i].to]) q[++tail]=edge[i].to;
                }
            }
        }
        void work()
        {
            ll ans=0;
            for (int i=1;i<=n;i++)
            {
                int x=q[i];from[x][x]=1;
                for (int j=p[x];j;j=edge[j].nxt)
                from[edge[j].to]|=from[x];
            }
            for (int i=n;i>=1;i--)
            {
                int x=q[i];to[x][x]=1;
                for (int j=p[x];j;j=edge[j].nxt)
                to[x]|=to[edge[j].to];
                ans+=((~(to[x]|from[x]))&cnt[(g[T]-g[x]+P)%P]).count();
            }
            cout<<(ans>>1);
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj5109.in","r",stdin);
        freopen("bzoj5109.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read(),S=read(),T=read();
        for (int i=1;i<=m;i++)
        {
            int x=read(),y=read(),z=read();
            addedge(x,y,z),addedge(y,x,z);
        }
        dijkstra(S,0),dijkstra(T,1);
        if (f[0][T]==0) {cout<<(1ll*n*(n-1)>>1);return 0;}
        for (int i=1;i<=n;i++)
        {
            if (d[0][i]+d[1][i]==d[0][T]) g[i]=1ll*f[0][i]*f[1][i]%P;
            cnt[g[i]][i]=1;
        }
        for (int i=1;i<=t;i+=2)
        {
            if (d[0][edge[i+1].to]+d[1][edge[i].to]+edge[i].len==d[0][T]) shortestpathDAG::addedge(edge[i+1].to,edge[i].to);
            if (d[0][edge[i].to]+d[1][edge[i+1].to]+edge[i].len==d[0][T]) shortestpathDAG::addedge(edge[i].to,edge[i+1].to);
        }
        shortestpathDAG::topsort();
        shortestpathDAG::work();
        return 0;
    }
  • 相关阅读:
    iOS13 present VC方法
    青囊奥语
    三元九运的排盘
    三元九运 笔记
    青囊经
    金钱卦起卦
    易经中九二六三是什么意思
    用神
    六爻预测中的世爻,应爻分别代表什么
    div2-1519-D-Maximum Sum of Products-dp
  • 原文地址:https://www.cnblogs.com/Gloid/p/9923644.html
Copyright © 2020-2023  润新知