洛谷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\n",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\n",an[i]);
146     return 0;
147 }
View Code

 

posted @ 2018-10-31 20:35  hehe_54321  阅读(188)  评论(0编辑  收藏  举报
AmazingCounters.com