• 洛谷P2505||bzoj2750 [HAOI2012]道路 && zkw线段树


    https://www.luogu.org/problemnew/show/P2505

    https://www.lydsy.com/JudgeOnline/problem.php?id=2750

    神奇的题目...

    题解

    好像dijkstra序(dijkstra遍历点的顺序)就是“最短路dag”的一个拓扑序

    错误记录:127行写成addto(d2[u],dn[v])

    然而此题卡常,学了一下zkw线段树优化dijkstra

      1 #pragma GCC optimize(3)
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<vector>
      6 #include<queue>
      7 using namespace std;
      8 #define fi first
      9 #define se second
     10 #define mp make_pair
     11 #define pb push_back
     12 typedef long long ll;
     13 typedef unsigned long long ull;
     14 struct pii
     15 {
     16     int fi,se;
     17     pii():fi(0),se(0){}
     18     pii(int a,int b):fi(a),se(b){}
     19 };
     20 bool operator<(const pii &a,const pii &b)
     21 {
     22     return a.fi<b.fi;
     23 }
     24 namespace SS
     25 {
     26     int M;pii d[5010];
     27     void init(int n)
     28     {
     29         int i;
     30         //zkw线段树是满二叉树,i的lc为i*2(i<<1),rc为i*2+1(i<<1|1)
     31         for(M=1;M<=n+1;M<<=1);
     32         //M-1表示除叶节点外共有多少节点
     33         //理论上写M<=n就够了,写M<=n+1是为了简化后面边界处理
     34         for(i=M;i<=M+M-1;++i)    d[i]=pii(0x3f3f3f3f,i-M);
     35         //d[M+0..M+n]存储"数组"a[0..n]即叶节点
     36         //注意叶节点下标从0开始
     37         for(i=M-1;i;--i)    d[i]=min(d[i<<1],d[i<<1|1]);
     38     }
     39     void set(int p,int x)
     40     {
     41         d[M+p]=pii(x,p);
     42         for(int i=(M+p)>>1;i;i>>=1)
     43             d[i]=min(d[i<<1],d[i<<1|1]);
     44     }
     45     inline pii qmin()
     46     {
     47         return d[1];
     48     }
     49 }
     50 struct E
     51 {
     52     int to,nxt,d;
     53 };
     54 const int md=1e9+7;
     55 void addto(int &x,int y)
     56 {
     57     x+=y;
     58     if(x>=md)    x-=md;
     59 }
     60 int mul(int x,int y){return ll(x)*y%md;}
     61 int an[5010];
     62 int n,m;
     63 namespace G
     64 {
     65     E e[5010];
     66     int f1[1510],ne;
     67     void me(int x,int y,int z)
     68     {
     69         e[++ne].to=y;e[ne].nxt=f1[x];f1[x]=ne;e[ne].d=z;
     70     }
     71     int d[1510],dn[1510],d2[1510];
     72     int tt[1510];
     73     bool vis[1510];
     74     void calc(int S)
     75     {
     76         int u,k,v,i;pii t;
     77         memset(d+1,0x3f,sizeof(d[0])*n);
     78         memset(dn+1,0,sizeof(dn[0])*n);
     79         memset(vis+1,0,sizeof(vis[0])*n);
     80         memset(d2+1,0,sizeof(d2[0])*n);
     81         tt[0]=0;
     82         SS::init(n);
     83         SS::set(S,0);
     84         d[S]=0;dn[S]=1;
     85         while(1)
     86         {
     87             t=SS::qmin();
     88             if(t.fi==0x3f3f3f3f)    break;
     89             //printf("at%d %d
    ",t.fi,t.se);
     90             u=t.se;SS::set(u,0x3f3f3f3f);
     91             //if(vis[u])    continue;
     92             tt[++tt[0]]=u;
     93             vis[u]=1;
     94             for(k=f1[u];k;k=e[k].nxt)
     95             {
     96                 v=e[k].to;
     97                 if(d[v]>d[u]+e[k].d)
     98                 {
     99                     d[v]=d[u]+e[k].d;
    100                     dn[v]=dn[u];
    101                     SS::set(v,d[v]);
    102                 }
    103                 else if(d[v]==d[u]+e[k].d)
    104                     addto(dn[v],dn[u]);
    105             }
    106         }
    107         for(i=tt[0];i>=1;--i)
    108         {
    109             u=tt[i];d2[u]=1;
    110             for(k=f1[u];k;k=e[k].nxt)
    111             {
    112                 v=e[k].to;
    113                 if(d[v]==d[u]+e[k].d)
    114                 {
    115                     addto(d2[u],d2[v]);
    116                 }
    117             }
    118         }
    119         for(i=1;i<=tt[0];++i)
    120         {
    121             u=tt[i];
    122             for(k=f1[u];k;k=e[k].nxt)
    123             {
    124                 v=e[k].to;
    125                 if(d[v]==d[u]+e[k].d)
    126                     addto(an[k],mul(dn[u],d2[v]));
    127             }
    128         }
    129     }
    130 };
    131 int main()
    132 {
    133     int i,x,y,z;
    134     scanf("%d%d",&n,&m);
    135     for(i=1;i<=m;++i)
    136     {
    137         scanf("%d%d%d",&x,&y,&z);
    138         G::me(x,y,z);
    139     }
    140     for(i=1;i<=n;++i)
    141     {
    142         G::calc(i);
    143     }
    144     for(i=1;i<=m;++i)
    145         printf("%d
    ",an[i]);
    146     return 0;
    147 }
    View Code
  • 相关阅读:
    Java学习笔记三十:Java小项目之租车系统
    Java学习笔记二十九:一个Java面向对象的小练习
    Java学习笔记二十八:Java中的接口
    Java学习笔记二十七:Java中的抽象类
    Java学习笔记二十六:Java多态中的引用类型转换
    Java学习笔记二十五:Java面向对象的三大特性之多态
    Java学习笔记二十四:Java中的Object类
    Java学习笔记二十三:Java的继承初始化顺序
    Java学习笔记二十二:Java的方法重写
    Java学习笔记二十一:Java面向对象的三大特性之继承
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9885745.html
Copyright © 2020-2023  润新知