1. 程式人生 > >解題:HAOI 2012 道路

解題:HAOI 2012 道路

can 起點 register oid scan spa gif spl dig

題面

這題不開O2怎麽過=。=

可能這種有關最短路的計數題做多了就有些感覺了......

以每個點為基準跑出一張最短路圖,然後對每個邊$(u,v)$統計兩個東西。一個$pre[u]$表示到達$u$這個起點的路徑條數,一個$nxt[v]$表示從$v$開始的最短路數,然後對每條邊來一下乘法原理。

然後是這兩個玩意的統計方法,$pre[]$可以在最短路圖上跑拓撲排序得出,$nxt[]$可以跑記憶化搜索,這樣統計的復雜度是$O(n+m)$的,總復雜度大概$O(nmlog$ $n)$?然而並不能卡過去......

技術分享圖片
  1 // luogu-judger-enable-o2
  2 #include<queue>
  3
#include<cstdio> 4 #include<cctype> 5 #include<cstring> 6 #include<algorithm> 7 using namespace std; 8 const int N=1505,M=5005; 9 const long long mod=1e9+7; 10 struct a{int node,dist;}; 11 bool operator < (a x,a y) 12 { 13 return x.dist>y.dist; 14 } 15
priority_queue<a> hp; 16 int dis[N],vis[N],pre[N],nxt[N],deg[N],ans[M],que[N]; 17 int p[N],noww[M],from[M],goal[M],val[M]; 18 int n,m,t1,t2,t3,cnt,f,b; 19 inline int read() 20 { 21 int ret=0; 22 char ch=getchar(); 23 while(!isdigit(ch)) 24 ch=getchar(); 25 while
(isdigit(ch)) 26 ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar(); 27 return ret; 28 } 29 void link(int f,int t,int v) 30 { 31 noww[++cnt]=p[f],p[f]=cnt; 32 goal[cnt]=t,val[cnt]=v,from[cnt]=f; 33 } 34 void Dijkstra(int s) 35 { 36 register int i; 37 memset(vis,0,sizeof vis); 38 memset(dis,0x3f,sizeof dis); 39 dis[s]=0,hp.push((a){s,0}); 40 while(!hp.empty()) 41 { 42 a tt=hp.top(); hp.pop(); int tn=tt.node; 43 if(vis[tn]) continue ; vis[tn]=true; 44 for(i=p[tn];i;i=noww[i]) 45 if(dis[goal[i]]>dis[tn]+val[i]) 46 { 47 dis[goal[i]]=dis[tn]+val[i]; 48 hp.push((a){goal[i],dis[goal[i]]}); 49 } 50 } 51 } 52 void getpre(int nde) 53 { 54 register int i,j; 55 for(i=1;i<=n;i++) 56 for(j=p[i];j;j=noww[j]) 57 if(dis[goal[j]]==dis[i]+val[j]) deg[goal[j]]++; 58 que[f=b=0]=nde,pre[nde]=1; 59 while(f<=b) 60 { 61 int tn=que[f++]; 62 for(i=p[tn];i;i=noww[i]) 63 if(dis[goal[i]]==dis[tn]+val[i]) 64 { 65 pre[goal[i]]+=pre[tn]; 66 if(!(--deg[goal[i]])) que[++b]=goal[i]; 67 } 68 } 69 } 70 void getnxt(int nde) 71 { 72 nxt[nde]=1; 73 for(int i=p[nde];i;i=noww[i]) 74 if(dis[goal[i]]==dis[nde]+val[i]) 75 { 76 if(!nxt[goal[i]]) getnxt(goal[i]); 77 nxt[nde]+=nxt[goal[i]]; 78 } 79 } 80 int main () 81 { 82 register int i,j; 83 scanf("%d%d",&n,&m); 84 for(int i=1;i<=m;i++) 85 scanf("%d%d%d",&t1,&t2,&t3),link(t1,t2,t3); 86 for(i=1;i<=n;i++) 87 { 88 Dijkstra(i); 89 memset(pre,0,sizeof pre); 90 memset(nxt,0,sizeof nxt); 91 memset(deg,0,sizeof deg); 92 getpre(i),getnxt(i); 93 for(j=1;j<=m;j++) 94 if(dis[from[j]]+val[j]==dis[goal[j]]) 95 ans[j]+=1ll*pre[from[j]]*nxt[goal[j]]%mod,ans[j]%=mod; 96 } 97 for(i=1;i<=m;i++) 98 printf("%d\n",ans[i]); 99 return 0; 100 }
View Code

解題:HAOI 2012 道路