洛谷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 }