1 /* 2 *題目大意: 3 *在一個有向圖中,求從s到t兩個點之間的最短路和比最短路長1的次短路的條數之和; 4 * 5 *算法思想: 6 *用A*求第K短路,目測會超時,直接在dijkstra算法上求次短路; 7 *將dist數組開成二維的,即dist[v][2],第二維分別用於記錄最短路和次短路; 8 *再用一個cnt二維數組分別記錄最短路和次短路的條數; 9 *每次更新路徑的條數時,不能直接加1,,應該加上cnt[u][k],k為次短路徑或者最短路徑的標記; 10 *圖有重邊,不能用鄰接矩陣存儲; 11 *不知道為什么,題目上說的是N and M, separated by a single space, with 2≤N≤1000 and 1 ≤ M ≤ 10000; 12 *而我的代碼硬是把N開成1W了才過,求解釋,RE了無數次,擦; 13 **/ 14 #include<iostream> 15 #include<cstdio> 16 #include<cstring> 17 #include<string> 18 #include<algorithm> 19 using namespace std; 20 21 const int N=11111; 22 const int M=111111; 23 const int INF=0xffffff; 24 25 struct node 26 { 27 int to; 28 int w; 29 int next; 30 }; 31 32 node edge[N]; 33 int head[N]; 34 35 int dist[N][2],cnt[N][2]; 36 bool vis[N][2]; 37 int n,m,s,t,edges; 38 39 void addedge(int u,int v,int w) 40 { 41 edge[edges].w=w; 42 edge[edges].to=v; 43 edge[edges].next=head[u]; 44 head[u]=edges++; 45 } 46 47 int dijkstra() 48 { 49 int k; 50 for(int i=0; i<=n; i++) 51 { 52 dist[i][0]=dist[i][1]=INF; 53 vis[i][0]=vis[i][1]=0; 54 cnt[i][0]=cnt[i][1]=0; 55 } 56 cnt[s][0]=1,dist[s][0]=0; 57 58 for(int i=1; i<=n*2; i++) 59 { 60 int u=-1; 61 int min_dist=INF; 62 for(int j=1; j<=n; j++) 63 for(int flag=0; flag<2; flag++) 64 if(!vis[j][flag]&&dist[j][flag]<min_dist) 65 { 66 min_dist=dist[j][flag]; 67 u=j; 68 k=flag; 69 } 70 if(u==-1) 71 break; 72 vis[u][k]=true; 73 for(int e=head[u]; e!=-1; e=edge[e].next) 74 { 75 int j=edge[e].to; 76 int tmp=dist[u][k]+edge[e].w; 77 78 if(tmp<dist[j][0])//tmp小於最短路徑長: 79 { 80 dist[j][1]=dist[j][0];//次短路徑長 81 cnt[j][1]=cnt[j][0];//次短路徑計數 82 dist[j][0]=tmp;//最短路徑長 83 cnt[j][0]=cnt[u][k];//最短路徑計數 84 } 85 86 else if(tmp==dist[j][0])//tmp等於最短路徑長: 87 { 88 cnt[j][0]+=cnt[u][k];//最短路徑計數 89 } 90 91 else if(tmp<dist[j][1])//tmp大於最短路徑長且小於次短路徑長: 92 { 93 dist[j][1]=tmp;//次短路徑長 94 cnt[j][1]=cnt[u][k];//次短路徑計數 95 } 96 97 else if(tmp==dist[j][1])//tmp等於次短路徑長: 98 { 99 cnt[j][1]+=cnt[u][k];//次短路徑計數 100 } 101 } 102 } 103 104 int res=cnt[t][0]; 105 if(dist[t][0]+1==dist[t][1])//判斷最短路和次短路是否相差1 106 res+=cnt[t][1]; 107 return res; 108 } 109 110 int main() 111 { 112 //freopen("C:\\Users\\Administrator\\Desktop\\kd.txt","r",stdin); 113 int tcase; 114 scanf("%d",&tcase); 115 while(tcase--) 116 { 117 edges=0; 118 scanf("%d%d",&n,&m); 119 memset(head,-1,sizeof(head)); 120 int u,v,w; 121 for(int i=0; i<m; i++) 122 { 123 scanf("%d%d%d",&u,&v,&w); 124 addedge(u,v,w); 125 } 126 scanf("%d%d",&s,&t); 127 printf("%d\n",dijkstra()); 128 } 129 return 0; 130 }
