zoukankan      html  css  js  c++  java
  • HAOI2012 道路

    题目链接 戳我

    最短路DAG上计数

    经过点的最短路计数和经过边的最短路计数实在不能一概而论。。。。qwqwqwqwqwq

    在做这道题之前,让我先捞上一张来自xyz32768大佬的图

    对于一条边(x,y)——求S到x的最短路径个数是很好求的一件事,对于一条边两个端点u,v,sum[v]+=sum[u]。那么顺序应当怎么确定呢?拓扑排序啊!但是怎么保证正确性呢?没有环啊!

    求上面那个好求,但是求y到T的最短路径个数就不太容易了。。。因为我们必须保证这些最短路都经过S->x,x->y,而不是从S直接到了y。还按照上面那个方法的话是有后效性的,无法DP。

    但是!但是!我们没有办法正着DP,难道就不能反过来了吗!sum[u]+=sum[v]不就可以了吗?

    至此,大功告成。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #define MAXN 100010
    #define mod 1000000007
    using namespace std;
    int n,m,t,tot,ll,rr;
    int cnt[MAXN],cnt1[MAXN],cnt2[MAXN],done[MAXN];
    int head[MAXN],ans[MAXN],ins[MAXN],dis[MAXN],pq[MAXN];
    struct Edge{int nxt,to,dis;}edge[MAXN<<1];
    struct Line{int u,v,w;}a[MAXN];
    int q[MAXN];
    inline void add(int from,int to,int dis)
    {
        edge[++t].nxt=head[from],edge[t].to=to;
        edge[t].dis=dis,head[from]=t;
    }
    inline void spfa(int x)
    {
        memset(dis,0x3f,sizeof(dis));
        memset(ins,0,sizeof(ins));
        ll=1,rr=0;
        q[++rr]=x;dis[x]=0;done[x]=1;
        while(ll<=rr)
        {
            int u=q[ll++];done[u]=0;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int v=edge[i].to;
                if(dis[u]+edge[i].dis<dis[v])
                {
                    dis[v]=dis[u]+edge[i].dis;
                    if(!done[v])
                        q[++rr],done[v]=1;
                }
            }
        }
        for(int i=1;i<=m;i++)
            if(dis[a[i].u]+a[i].w==dis[a[i].v])
                ins[i]=1;
    }
    inline void topo_sort(int x)
    {
        memset(cnt,0,sizeof(cnt));
        memset(cnt1,0,sizeof(cnt1));
        memset(cnt2,0,sizeof(cnt2));
        ll=1,rr=0,tot=0;
        cnt1[x]=1;
        q[++rr]=x;
        for(int i=1;i<=m;i++) if(ins[i]) cnt[a[i].v]++;
        while(ll<=rr)
        {
            int u=q[ll++];
            pq[++tot]=u;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int v=edge[i].to;
                if(!ins[i]) continue;
                cnt[v]--;
                if(!cnt[v]) q[++rr]=v;
                cnt1[v]=(cnt1[v]+cnt1[u])%mod;
            }
        }
        for(int i=tot;i;i--)
        {
            int u=pq[i]; cnt2[u]++;
            for(int j=head[u];j;j=edge[j].nxt)
            {
                if(!ins[j]) continue;
                int v=edge[j].to;
                cnt2[u]=(cnt2[u]+cnt2[v])%mod;
            }
        }
    }
    inline void print()
    {
        for(int i=1;i<=n;i++) printf("ins[%d]=%d
    ",i,ins[i]);
        for(int i=1;i<=n;i++) printf("dis[%d]=%d
    ",i,dis[i]);
        for(int i=1;i<=n;i++) printf("cnt1[%d]=%d
    ",i,cnt1[i]);
        for(int i=1;i<=n;i++) printf("cnt2[%d]=%d
    ",i,cnt2[i]);
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            a[i].u=u,a[i].v=v,a[i].w=w;
            add(u,v,w);
        }
        for(int i=1;i<=m;i++) 
        {
            printf("i=%d
    ",i);
            spfa(i);
            topo_sort(i);
            print();
            for(int i=1;i<=m;i++)
                if(ins[i])
                    ans[i]=(ans[i]+1ll*cnt1[a[i].u]*cnt2[a[i].v]%mod)%mod;
        }
        for(int i=1;i<=m;i++)
                printf("%d
    ",ans[i]);
        return 0;
    }
    
    
    

    呜呜呜好吧我承认这个代码在BZOJ上没有办法过。。。会T一个点。。。。。。但是把STL队列手写一下。。应该就可以了。。。。。。
    不开O2惨无人道啊qwqwq

  • 相关阅读:
    第三方驱动备份与还原
    Greenplum 解决 gpstop -u 指令报错
    yum安装(卸载)本地rpm包的方法(卸载本地安装的greenplum 5.19.rpm)
    Java JUC(java.util.concurrent工具包)
    netty 详解(八)基于 Netty 模拟实现 RPC
    netty 详解(七)netty 自定义协议解决 TCP 粘包和拆包
    netty 详解(六)netty 自定义编码解码器
    netty 详解(五)netty 使用 protobuf 序列化
    netty 详解(四)netty 开发 WebSocket 长连接程序
    netty 详解(三)netty 心跳检测机制案例
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10462240.html
Copyright © 2011-2022 走看看