题目大意:
希望求出走出最短路的方法总数,如果次短路只比最短路小1,那也是可取的
输出总的方法数
这里n个点,每个点有最短和次短两种长度
这里采取的是dijkstra的思想,相当于我们可以不断找到更新到的最短长度来更新其他长度,保证之前的所有可取的最短长度都已经更新的情况下,这样是除了第一个点的最短路为0已知,还需要更新2*n-1次,如果从一个点的位置出发更新了其他点,那么这个位置就不再作为可更新点~~这里都是暴力找最优的可更新的点~~不知道如何做到像普通的dijkstra那种log级别的找点~~
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 #define N 1005 7 #define M 10005 8 #define clr(a,b) memset(a,b,sizeof(a)) 9 struct Edge{ 10 int x,y,d,next; 11 Edge(int x=0,int y=0,int d=0,int next=0):x(x),y(y),d(d),next(next){} 12 }e[M<<1]; 13 int first[N] , tot , n , m , s , t; 14 void add_edge(int x,int y,int d) 15 { 16 e[tot] = Edge(x,y,d,first[x]); 17 first[x] = tot++; 18 } 19 int dis[N][2] , cnt[N][2] , vis[N][2]; 20 void dijkstra(int s , int t) 21 { 22 clr(dis,0x3f);clr(vis,0);clr(cnt,0); 23 dis[s][0]=0;cnt[s][0]=1; 24 for(int i=1;i<2*n;i++){ 25 int a=0 , b=0 , curd=0x7fffffff; 26 for(int j=1;j<=n;j++){ 27 if(dis[j][0]<curd && !vis[j][0]) curd=dis[j][0] , a=j,b=0; 28 if(dis[j][1]<curd && !vis[j][1]) curd=dis[j][1] , a=j,b=1; 29 } 30 // cout<<a<<" "<<b<<" "<<curd<<endl; 31 vis[a][b]=1; 32 for(int i=first[a];~i;i=e[i].next){ 33 int v = e[i].y , nowd=curd+e[i].d; 34 if(nowd<dis[v][0]){ 35 dis[v][1]=dis[v][0];cnt[v][1]=cnt[v][0]; 36 dis[v][0]=nowd;cnt[v][0]=cnt[a][b]; 37 } 38 else if(nowd == dis[v][0]){ 39 cnt[v][0]+=cnt[a][b]; 40 } 41 else if(nowd <dis[v][1]){ 42 dis[v][1]=nowd ;cnt[v][1]=cnt[a][b]; 43 } 44 else if(nowd==dis[v][1]){ 45 cnt[v][1]+=cnt[a][b]; 46 } 47 } 48 } 49 // cout<<cnt[t][0]<<" "<<cnt[t][1]<<endl; 50 if(dis[t][1]-1 == dis[t][0]) cnt[t][0]+=cnt[t][1]; 51 printf("%d " , cnt[t][0]); 52 } 53 int main() 54 { 55 // freopen("a.in" , "r" , stdin); 56 int T; 57 scanf("%d" , &T); 58 while(T--){ 59 scanf("%d%d" , &n , &m); 60 clr(first,-1);tot=0; 61 for(int i=0; i<m ; i++){ 62 int x,y,d; 63 scanf("%d%d%d" , &x, &y , &d); 64 add_edge(x , y , d); 65 } 66 67 scanf("%d%d" , &s , &t); 68 dijkstra(s,t); 69 } 70 71 return 0; 72 }