1003 Emergency

在这里插入图片描述
在这里插入图片描述
思路解析:
这是一道典型的最短路径的问题,迪杰斯特拉算法的变形。
用num数组记录到当前节点的最短路径条数,当路径长度相等,即dist[u] + gra[u][v] == dist[v]时,此时的路径条数,需要在前一个节点的路径个数基础上,加上该节点的,即num[v] += num[u];还需要判断,如果到达当前节点的权值(救援队数)是否大于,本来的权值,如果是则要w[v] = w[u] + weight[v];

在正式开始代码之前,先补充一些Dikjstra算法的知识:
Dikjstra算法只能找到唯一的最短路径,换言之,它只管找路径,不管多少条,只要找出来一条就可以,所以需要在原先的基础上进行一些改动:

代码模板:

void dikjstra(Graph* gra, int v0) {
	//初始化
	for(int i = 0; i < n; i++){
	    S[i] = false;
	    dist[i] = gra[i][v0];
	    
	    ...//比如路径信息啥的
	}
	dist[v0] = 0;
	//S[v0] = true;  //如果有多条最短路径,就不要写这一行了,因为该行一开始就默认从v0开始就只有一条路径。
	

    //对剩余的n-1条路径搜索最短路径
	for(int i = 0; i < n; i){//至于是执行n次,还是n-1次,要看是否
	     int u = -1;   //存在多条路径,如果实在记不住,直接从0开始执行n次也是
	     int min = INF;//OK的,当然如果考试系统不卡测试点的话.
	     for(int j = 0; j < n; j++){
	         if(!S[j] && dist[j] < min){
	              u = j;
	              min = dist[j];
	         }
	     } 
	     S[u] = true;      
	     //更新最短路径
	     for(int v = 0; v < n; v++){
	          if(!S[v] && gra[u][v] != INF){
	              if(dist[u] + gra[u][v] < dist[v]){
	                  dist[v] = dist[u] + gra[u][v];
	                  
	                  ...//更新权值,或记录个数等等
	              }
	          }
	     }        
	
	}
}

示例代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#define INF (~(0x1<<31))//31位系统的最大值,相当于正无穷
using namespace std;
int gra[510][510], weight[510], num[510], w[510],dist[510];
bool S[510];//默认初始为false
int n, m, c1, c2;
int main() {
	scanf("%d %d %d %d", &n, &m, &c1, &c2);
	for (int i = 0; i < n; i++) {
		scanf("%d", &weight[i]);//读入权值
	}
	int a, b, c;
	for (int i = 0; i < m; i++) {
		scanf("%d %d %d", &a, &b, &c);
		gra[a][b] = gra[b][a] = c;
	}
	fill(gra[0], gra[0] + 510 * 510, INF);
	fill(dist, dist + 510, INF);
	dist[c1] = 0;
	num[c1] = 1;
	w[c1] = weight[c1];
	for (int i = 0; i < n; i++) {
		int u = -1;
		int min = INF;
		for (int j = 0; j < n; j++) {
			if (!S[j] && dist[j] < min) {
				min = dist[j];
				u = j;
			}
		}
		S[u] = true;
		for (int v = 0; v < n; v++) {
			if (!S[v] && gra[u][v] != INF) {
				if (dist[u] + gra[u][v] < dist[v]) {//找到了新的最短路径
					num[v] = num[u];
					w[v] = w[u] + weight[v];
					dist[v] = dist[u] + gra[u][v];
				}
				else if (dist[u] + gra[u][v] == dist[v]) {//找到了一条相等的
					num[v] += num[u];
					if (w[u] + weight[v] > w[v]) {
						w[v] = w[u] + weight[v];
					}
				}
			}
		}
	}
	printf("%d %d", num[c2], w[c2]);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值