ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

patA1003

2022-04-26 18:33:15  阅读:167  来源: 互联网

标签:patA1003 cid int MAX disto visit 节点


思路:这道题在基础dijkstra算法的基础上增加了两个新的标尺,即最短路径数和最短路径中点权和的最大值。由于这两个标尺比较简单,所以对dijkstra的松弛部分进行补充即可。使用两个数组pnum和wnum分别存储某个节点的当前最短路径数和最短路径中点权和的当前最大值,记得要对源点s的相应数据进行初始化。松弛点的时候要将情况细分为relax后disto的值与原来的值是严格小于或者等于。
选择disto值最小的节点时,使用stl的priority_queue容器,不过要对其进行改造,使之成为一个小根堆,数值越小优先级越高。具体的方法可参考文章:https://www.cnblogs.com/bianchengjun520/p/5321039.html
注意事项:当使用0x形式为数组赋值时,需要手动使用fill函数,不能用{}初始化。



代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>


using namespace std;

//用于邻接表
struct node {
	int id;		//另一点的id
	int w;		//边权
	node(int x,int y):id(x),w(y){}
};	

//用于优先队列
struct vertex {
	int id;
	int d;		//当前到源点的最短距离
	vertex(int x,int y):id(x),d(y){}
};

//优先队列的比较函数
struct cmp {
	bool operator ()(vertex& a, vertex& b) {
		return a.d>b.d;	//最小值优先
	}
};

//INF
const int INF = 0x3fffffff;
//最大节点数 
const int MAX = 500;
//节点数
int N;
//边数
int M;
//源点
int s;
//汇点
int t;
//邻接表
vector<node> adj[MAX];
//各城市救援组数量
int resc[MAX] = { 0 };
//标记节点是否已在最短路径树中
bool visit[MAX] = { false };
//disto数组
int disto[MAX];
//储存当前到各个结点的最短路径数
int pnum[MAX] = { 0 };
//储存当前到每个点的最短路径中的最大点权
int wnum[MAX] = { 0 };


//读输入
void input() {
	cin >> N >> M>>s>>t;
	for (int i = 0; i < N; i++) {
		cin >> resc[i];
	}
	for (int i = 0; i < M; i++) {
		int u, v, w;
		cin >> u >> v >> w;
		adj[u].push_back(node(v, w));
		adj[v].push_back(node(u, w));
	}
}


//求解
void dijkstra() {
	//当前节点的id
	int cid = s;

	//计数器
	int count = N;	

	while (count--) {
		//若当前节点是目标节点,退出
		if (cid == t)
			break;

		//松弛当前节点
		for (int i = 0; i < adj[cid].size(); i++) {
			int v = adj[cid][i].id;
			int w = adj[cid][i].w;

			if (!visit[v] && disto[cid]+w<disto[v]) {
				//更新disto,wnum,pnum三个数组
				disto[v] = disto[cid] + w;
				wnum[v] = resc[v] + wnum[cid];
				pnum[v] = pnum[cid];
				continue;
			}

			if (!visit[v] && disto[cid] + w == disto[v]) {
				//更新wnum,pnum2个数组
				if (wnum[cid] + resc[v] > wnum[v])
					wnum[v] = wnum[cid] + resc[v];
				
				pnum[v] += pnum[cid];
				continue;
			}
		}

		//从pq中选出当前disto值最小的节点作为下一个节点
		//优先队列,使用小根堆
		priority_queue<vertex, vector<vertex>, cmp> pq;
		//将所有没有visit的节点加入优先队列
		for (int i = 0; i < N; i++) {
			if(!visit[i])
				pq.push(vertex(i, disto[i]));
		}
			
		//找到disto值最小的节点,更新cid
		if (pq.size() > 0) {
			cid = pq.top().id;
			//将cid对应的visit置true
			visit[cid] = true;
		}
	}

}



int main(void) {
	fill(disto, disto + MAX, INF);
	input();

	//将disto的源点对应的值设为0,visit设为true,并设置pnum,wnum
	disto[s] = 0;
	visit[s] = true;
	pnum[s] = 1;
	wnum[s] = resc[s];

	//计算
	dijkstra();
	//输出
	cout << pnum[t] << " "<<wnum[t] << endl;

	return 0;
}

当然,这个题也可用更常规的方法来做,即找出所有最短路径并用path数组储存,然后对路径逐一判断。

标签:patA1003,cid,int,MAX,disto,visit,节点
来源: https://www.cnblogs.com/biginsulator/p/16195967.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有