1003 Emergency (25 分)

news/2024/7/15 17:28:18 标签: 算法, 图论, dijkstra

跟着柳婼学姐学习的笔记ヾ(≧▽≦*)o

  • 题意
  • 分析
  • CODE
  • CODE V2——BF解法

原题目: 1003 Emergency (25 分).

题意

一张地图,城市间由道路连接,并标有每个城市的救援队数量以及每条路的长度。
给出城市数N(≤500,编号0~N-1),道路数M,所在城市C1和要救援的城市C2。接着N个整数给出每个城市的救援队数量,接着M行给出城市对和距离(C1到C2至少有一条路)。
① 求C1到C2的最短路径数量,
② 最短路径上的救援队最多数量。

分析

  1. 最短路径问题(单源且正值)——Dijkstra算法
  2. 在优化部分,增加:① 更新最短路径数量,② 更新点权值(城市救援队数量)。

CODE

#include <iostream>
using namespace std;
const int maxv = 510;
const int inf = 1000000000;
int n, m, c1, c2;
int G[maxv][maxv], weight[maxv];  //图,救援队数量
int dis[maxv], num[maxv], w[maxv];  //最短路径长度,最短路径数量,最大救援队数量(均从c1开始到各顶点)
bool vis[maxv];  //标记访问

void Dijkstra(int c1);
int main()
{
    cin >> n >> m >> c1 >> c2;
    for ( int i=0; i<n; i++ )
        cin >> weight[i];
    //建图
    fill(G[0], G[0]+maxv*maxv, inf);  //初始化
    for ( int i=0; i<m; i++ ){
        int a, b, c;
        cin >> a >> b >> c;
        G[a][b] = G[b][a] = c;
    }
    Dijkstra(c1);
    printf("%d %d", num[c2], w[c2]);
    
    return 0;
}
void Dijkstra(int c1){  //起点为c1
    //初始化
    fill(dis, dis+maxv, inf);
    dis[c1] = 0;
    w[c1] = weight[c1];  //救援队
    num[c1] = 1;  //c1到c1的最短路径数量
    //遍历所有城市
    for ( int i=0; i<n; i++ ){
        //找到u使d[u]最小
        int u = -1, mindis = inf;
        for ( int j=0; j<n; j++ ){
            if ( vis[j]==false && dis[j]<mindis ){
                u = j;
                mindis = dis[j];
            }
        }
        //没找到u
        if ( u==-1 ) return;
        //找到u
        vis[u] = true;  //标记访问
        //以u为中介点遍历其邻接点v,优化d[v]
        for ( int v=0; v<n; v++ ){
            if ( vis[v]==false && G[u][v]!=inf ){
                if ( dis[u]+G[u][v]<dis[v] ){
                    dis[v] = dis[u] + G[u][v];  //优化距离
                    num[v] = num[u];  //起点到v的最短路径数量与到u的数量相同
                    w[v] = w[u] + weight[v];  //更新能到达v的救援队数量
                }
                else if ( dis[u]+G[u][v]==dis[v] ){  //多条最短路径
                    num[v] += num[u];  //从原来的路径到v + 从新路径到v
                    if ( w[u]+weight[v]>w[v] )
                        w[v] = w[u] + weight[v];  //要求救援队数量最多
                }
            }
        }
    }
}

CODE V2——BF解法

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
const int maxv = 510;
const int inf = 1000000000;
struct node{
	int v, dis;  //邻接点,邻接边的边权
};
vector<node> Adj[maxv];  //邻接表
int n, m, st, ed,weight[maxv];  //st和ed分别为起点和终点,weight[]记录点权
int d[maxv], w[maxv], num[maxv];  //w[]记录最大点权之和,num[]记录最短路径条数
set<int> pre[maxv];  //前驱

void Bellman(int s){
	//初始化
	fill(d, d+maxv, inf);
	d[s] = 0;
	w[s] = weight[s];
	num[s] = 1;  //s到s有1条路径
	//循环n-1趟,生成d[]
	for ( int i=0; i<n-1; i++ ){
		for ( int u=0; u<n; u++ ){  //遍历每个顶点
			for ( int j=0; j<Adj[u].size(); j++ ){
				int v = Adj[u][j].v;  //u的邻接点
				int dis = Adj[u][j].dis;  //邻接边的边权
				if ( d[u]+dis<d[v] ){
					d[v] = d[u] + dis;
					w[v] = w[u] + weight[v];
					num[v] = num[u];   //覆盖
					pre[v].clear();
					pre[v].insert(u);
				}
				else if ( d[u]+dis==d[v] ){  //不止一条最短路径
					if ( w[u]+weight[v]>w[v] ){  //点权更大时
						w[v] = w[u] + weight[v];
					}
					pre[v].insert(u);
					//重新统计num[v]
					num[v] = 0;
					for ( auto it=pre[v].begin(); it!=pre[v].end(); it++ ){
						num[v] += num[*it];
					}
				}
			}
		}
	}
}
int main()
{
	cin >> n >> m >> st >> ed;
	for ( int i=0; i<n; i++ )
		cin >> weight[i];
	int u, v, wt;
	for ( int i=0; i<m; i++ ){
		cin >> u >> v >> wt;
		Adj[u].push_back(node{v,wt});
		Adf[v].push_back(node{u,wt});
	}
	Bellman(st);
	printf("%d %d", num[ed], w[ed]);
	return 0;
}

http://www.niftyadmin.cn/n/1165009.html

相关文章

算法提高之图(《算法笔记》)

写个目录图的存储图的遍历深度优先搜索&#xff08;DFS&#xff09;法遍历图[PAT A1034] 1034 Head of a Gang(30)广度优先搜索&#xff08;BFS&#xff09;法遍历图[PAT A1076] Forwards on Weibo(30)最短路径Dijkstra算法——解决单源最短路径问题最短距离最短路径最短路径不…

1030 Travel Plan (30 分)

跟着柳婼学姐学习的笔记ヾ&#xff08;≧▽≦*&#xff09;o题意分析CODE原题目&#xff1a; 1030 Travel Plan (30 分).题意 给出城市数N&#xff08;≤500&#xff0c;从0编号&#xff09;&#xff0c;道路数M&#xff0c;起点城市S和终点城市D&#xff08;均不超过500的整…

jupyter notebook文件保存路径

本文为学习记录 来源于感谢大佬&#xff0c;点此跳转 查看文件默认存储路径 import os print(os.path.abspath(.))更改默认存储路径 STEP1 找到配置文件 ①菜单中打开Anaconda Prompt ②输入命令 jupyter notebook --generate-config ③根据上面运行处的路径打开C:\Users\XX…

设置csdn文章的字体样式/格式

感谢&#x1f449;https://blog.csdn.net/qq_43232869/article/details/108013915 想要这样的样式&#x1f447; used to copy感谢&#x1f449;https://blog.csdn.net/qq_41320782/article/details/103930720 想要缩进&#x1f447; 两个汉字为参考     试一下 &…

记录各种导入包/模块出错的解决

写个目录sklearn无法导入plot_confusion_matrix安装CythonCython文件编译sklearn无法导入plot_confusion_matrix 这个模块貌似需要scikit-learn 0.22以上的版本才行。 先用anaconda更新了一下 →在anaconda prompt中 conda update scikit-learn但是还是未能导入成功&#xf…

PAT 1001 A+B Format

题目描述 刚开始拿到这道题不知道C也有数字转字符串的函数&#xff0c;自己手写了一个tostring&#xff0c;但转换后的字符串是倒置的&#xff0c;在输出时对于某些情况考虑不全面&#xff0c;导致没有全对&#xff0c;改了几次才改全对&#xff0c;代码繁琐冗长。 #include&l…

PAT 1002 A+B for Polynomials

题目描述 分析&#xff1a; 对于此题&#xff0c;题意很简单&#xff0c;就是两个多项式相加进行&#xff0c;完后输出系数和值 我采用map进行多项式相加&#xff0c;但是不知道问题出在哪&#xff0c;思路和大佬完全一样&#xff0c;但是得分只能得到一部分分数&#xff08;…

PAT 1008 Elevator

题目描述 简单模拟题&#xff08;水题 &#xff09; #include<cstdio> using namespace std; int main(){int n;scanf("%d",&n);int floor0;int future;int timen*5;while(n--){scanf("%d",&future);if(future>floor){time(future-floo…