1003 Emergency(考察Dijkstra内嵌第二标尺或Dijkstra+DFS)
大致题意就是给出一个图、每个顶点的点权、顶点之间的边权、起点和终点。求出从起点到终点的最短路径的数量、以及最短路径上的最大点权之和。
这是一道模板题,要先记住大体流程,然后反复练习,较难头疼。。。
1 #include<iostream> 2 using namespace std; 3 4 const int maxn = 510; 5 const int inf = 0x3fffffff;//无穷大 6 //第一标尺 7 int n,m,st,ed,G[maxn][maxn];//顶点个数、邻接矩阵 8 bool visited[maxn] = {false};//标记是否被访问过数组 9 int d[maxn]; //从起点S到其它顶点的最短距离 10 11 //第二标尺 12 int num[maxn];//从起点S到其它顶点的最短路径数量之和 13 int weight[maxn],w[maxn];//各个顶点的点权、从起点S到其它顶点的最大点权之和 14 15 void dijkstra(int s) {//s为起点 16 //第一步,初始化d[],num[],w[] 17 fill(visited,visited+maxn,false); 18 fill(d,d+maxn,inf); 19 fill(num,num+maxn,0); 20 fill(w,w+n,0); 21 d[s] = 0; 22 num[s] = 1; 23 w[s] = weight[s]; 24 //第二步,循环 n次 25 for(int i = 0; i < n; ++i) { 26 // 第三步,遍历所有顶点u,找到最小的d[u],并标记为已访问 27 int u = -1, MIN = inf; 28 for(int j = 0; j < n; ++j) { 29 if(visited[j] == false && MIN > d[j]) { 30 u = j; 31 MIN = d[j]; 32 } 33 } 34 if(u == -1) return ;//剩下的顶点和起点不连通 35 visited[u] = true; 36 //第五步,遍历所有顶点v,用点 u优化d[v] 37 for(int v = 0; v < n; ++v) { 38 if(visited[v] == false && G[u][v] != inf) { 39 if(d[u] + G[u][v] < d[v]) {//经过u可以优化d[v] 40 d[v] = d[u]+G[u][v]; //覆盖d[v] 41 num[v] = num[u]; //覆盖num[v] 42 w[v] = w[u] + weight[v];//覆盖w[v] 43 } else if(d[u] + G[u][v] == d[v]) { //找到一条相同长度的路径 44 if(w[u] + weight[v] > w[v])//覆盖w[v] 45 w[v] = w[u] + weight[v]; 46 num[v] += num[u]; 47 } 48 } 49 } 50 } 51 } 52 int main() { 53 cin>>n>>m>>st>>ed; 54 for(int i = 0; i < n; ++i) cin>>weight[i]; //初始化各顶点的点权 55 //初始化邻接矩阵 56 fill(G[0],G[0]+maxn*maxn,inf);//别忘了 57 int c1,c2,L; 58 for(int i = 0 ; i < m ; ++i) { 59 cin>>c1>>c2>>L; 60 G[c1][c2] = L; 61 G[c2][c1] = L; 62 } 63 dijkstra(st);//算法入口 64 printf("%d %d",num[ed],w[ed]); 65 return 0; 66 }


浙公网安备 33010602011771号