zoukankan      html  css  js  c++  java
  • 2018.12.20-dtoj-4084-演艺(b)

     

    题目描述:

     

    一张 N 个点 M 条无向边的图,节点编号为 1 到 N,每条边具有一个正整数的长度。 

     

    假定黄花敦会从 S 点出发到达 T 点,并且只会走最短路,wxh 和 wsq 会在 A 点和 B 点 埋伏黄花敦。 

     

    为了保证一定能埋伏到黄花敦,同时 wxh 又想制造单独和黄花敦相处的机会,A 点和 B 点必须满足:黄花敦所有可能路径中,必定会经过 A 点和 B 点中的任意一点且不存在一条 路径同时经过 A 点和 B 点。 

     

    Wxh 想知道满足上面两个条件的 A,B 点对有多少个,交换 A,B 的顺序算相同的方案。

     

    算法:dijk,bitset,拓扑

    思路:

    首先先建出最短路网,在最短路网中拓扑处理出经过每个点的最短路条数,考虑对于满足条件的AB,经过A的条数与经过B的条数总和等于总最短路条数,且经过两点的条数不重复。

    我们有了每个点的最短路条数,考虑怎么把重复的点去掉。重复两点即至少有一条路径能从其中一个点到达另一个点,于是我们跑两遍拓扑,处理出谁能走到我和我能走到谁,即可能重复的点。

    然后我们用bitset维护,对于一个点,把权值等于(总最短路树-经过我的最短路数)的bitset和可能重复的点的bitset&起来,即重复的点,再用权值=(总最短路树-经过我的最短路数)的bitset^重复的点数,即可以与我匹配的点的数目,用.count()计算其中1的数目即可。效率是O(n2/32)

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define LL long long
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=5e4+5,p=998244353;const LL inf=1e18;
    int n,m,s,T,head[N],ne[N<<1],to[N<<1],cnt,w[N<<1],tot;LL d[N],ds[N],dt[N],in[N],out[N];int iw[N],ow[N];LL ans;
    struct data{int l,r,w;}t[N];queue<int> Q;bitset<N> val[N],k[N],f,g[N];map<int,int> ma;
    struct node{int x;LL d;bool operator<(const node&t1)const{return d>t1.d;}};priority_queue<node> q;
    il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x;}
    il void insert(int x,int y,int z){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;w[cnt]=z;}
    il void ins(int x,int y){in[y]++;ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;}
    il int mu(int x,int y){if(x+y>=p)return x+y-p;return x+y;}
    il void dijk(int S){
        for(int i=1;i<=n;i++)d[i]=inf;d[S]=0;q.push((node){S,d[S]});
        while(!q.empty()){
            node now=q.top();q.pop();int x=now.x;if(now.d!=d[x])continue;
            for(int i=head[x];i;i=ne[i]){
                if(d[to[i]]<=d[x]+w[i])continue;
                d[to[i]]=d[x]+w[i];q.push((node){to[i],d[to[i]]});
            }
        }
    }
    int main()
    {
        n=read();m=read();s=read();T=read();
        for(int i=1;i<=m;i++){
            int x=read(),y=read(),w=read();
            t[i]=(data){x,y,w};insert(x,y,w);insert(y,x,w);
        }
        dijk(s);for(int i=1;i<=n;i++)ds[i]=d[i];
        dijk(T);for(int i=1;i<=n;i++)dt[i]=d[i];
        for(int i=1;i<=n;i++)head[i]=0;cnt=0;
        for(int i=1;i<=m;i++){
            int x=t[i].l,y=t[i].r;
            if(ds[x]+dt[y]+t[i].w==ds[T])ins(x,y);
            if(dt[x]+ds[y]+t[i].w==ds[T])ins(y,x);
        }
        Q.push(s);iw[s]=1;
        while(!Q.empty()){
            int x=Q.front();Q.pop();k[x][x]=1;
            for(int i=head[x];i;i=ne[i]){
                iw[to[i]]=mu(iw[to[i]],iw[x]);k[to[i]]|=k[x];
                if(--in[to[i]]==0)Q.push(to[i]);
            }
        }
        for(int i=1;i<=n;i++)head[i]=0,in[i]=0;cnt=0;
        for(int i=1;i<=m;i++){
            int x=t[i].l,y=t[i].r;
            if(ds[x]+dt[y]+t[i].w==ds[T])ins(y,x);
            if(dt[x]+ds[y]+t[i].w==ds[T])ins(x,y);
        }
        Q.push(T);ow[T]=1;
        while(!Q.empty()){
            int x=Q.front();Q.pop();g[x][x]=1;
            for(int i=head[x];i;i=ne[i]){
                ow[to[i]]=mu(ow[to[i]],ow[x]);g[to[i]]|=g[x];
                if(--in[to[i]]==0)Q.push(to[i]);
            }
        }
        for(int i=1;i<=n;i++){
            iw[i]=1ll*iw[i]*ow[i]%p;
            if(!ma[iw[i]])ma[iw[i]]=++tot;
            val[ma[iw[i]]][i]=1;k[i][i]=1;
        }
        int sum=iw[T];
        for(int i=1;i<=n;i++){
            int R=ma[mu((sum-iw[i])%p,p)];
            f=val[R]&(k[i]|g[i]);
            f=val[R]^f;ans+=f.count();
        }
        printf("%lld
    ",ans>>1ll);
        return 0;
    }
    View Code

    //全场最慢...

  • 相关阅读:
    Android开发总结
    LeakCanary原理分析
    机器学习
    Kivy 中文教程 实例入门 简易画板 (Simple Paint App):2. 实现绘图功能
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 3. 循环
    Kivy 中文教程 实例入门 简易画板 (Simple Paint App):1. 自定义窗口部件 (widget)
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 2. 变量
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 1. 神秘朋友
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 0. 准备工作
    远程显示(操作) 服务器 GUI 程序(图形化界面) (基于 X11 Forwarding + Centos + MobaXterm)
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10153614.html
Copyright © 2011-2022 走看看