L2-001. 紧急救援/1003. Emergency (25)

L2-001. 紧急救援

作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。

输入格式:

输入第一行给出4个正整数N、M、S、D,其中N(2<=N<=500)是城市的个数,顺便假设城市的编号为0~(N-1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。

输出格式:

第一行输出不同的最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出首尾不能有多余空格。

输入样例:

4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2

输出样例:

2 60
0 1 3

我自己编的输入样例:

4 5 0 3
20 30 20 20
0 1 1
1 3 1
0 3 2
0 2 1
2 3 1

输出样例:

3 70
0 1 3


  1. Emergency (25)
    ====================
    As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.

Input

Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (<= 500) - the number of cities (and the cities are numbered from 0 to N-1), M - the number of roads, C1 and C2 - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c1, c2 and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C1 to C2.

Output

For each test case, print in one line two numbers: the number of different shortest paths between C1 and C2, and the maximum amount of rescue teams you can possibly gather.
All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.

Sample Input

5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1

Sample Output

2 4

L2-001.紧急救援 AC代码:

/*
	Name:L2-001紧急救援 
	Author: spencercjh
	Date:2017年11月15日15:41:14 
	Description:团体程序设计天梯赛-练习集
	reference:算法笔记 P380 
	key word:Dijkstra Dfs 
*/
#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<functional>
#include<numeric>
#include<stack>
using namespace std;
const int MAXV=510;
const int INF=0x3f3f3f3f;
int n,m,st,ed,G[MAXV][MAXV],weight[MAXV];
int d[MAXV],w[MAXV],num[MAXV],pre[MAXV];
bool vis[MAXV]= {false};
vector<int> ans;
void Dijkstra(int s) {
	//初始化边权、点权、边数数组 
	fill(d,d+MAXV,INF);
	fill(num,num+MAXV,0);
	fill(w,w+MAXV,0);
	//设置起点数据 
	d[s]=0;
	w[s]=weight[s];
	num[s]=1;
	//初始化路径数组 
	for(int i=0; i<n; i++) {
		pre[i]=i;
	}
	//Dijkstra外层循环 
	for(int i=0; i<n; i++) {
		int u=-1,MIN=INF;//u使d[u]最小,MIN存放该最小的d[u] 
		for(int j=0; j<n; j++) {//找到未访问的顶点中d[u]最小的 
			if(vis[j]==false&&d[j]<MIN) {
				u=j;
				MIN=d[j];
			}
		}
		if(u==-1) {//找不到小于INF的d[u],说明剩下的顶点和起点s不连通 
			return;
		}
		vis[u]=true;
		for(int v=0; v<n; v++) {
			if(vis[v]==false&&G[u][v]!=INF) {
				if(d[u]+G[u][v]<d[v]) {
					d[v]=d[u]+G[u][v];
					w[v]=w[u]+weight[v];
					num[v]=num[u];
					pre[v]=u;
				} else if(d[u]+G[u][v]==d[v]) {
					if(w[u]+weight[v]>w[v]) {
						w[v]=w[u]+weight[v];
						pre[v]=u;
					}
					num[v]+=num[u];
				}
			}
		}
	}
}
void DFS_Path(int s,int v) {
	if(v==s) {
		ans.push_back(s);
		return;
	}
	DFS_Path(s,pre[v]);
	ans.push_back(v);
}
int main() {
	scanf("%d %d %d %d",&n,&m,&st,&ed);
	for(int i=0; i<n; i++) {
		scanf("%d",&weight[i]);
	}
	fill(G[0],G[0]+MAXV*MAXV,INF);
	for(int i=0; i<m; i++) {
		int u,v;
		scanf("%d %d",&u,&v);
		scanf("%d",&G[u][v]);
		G[v][u]=G[u][v];
	}
	Dijkstra(st);
	printf("%d %d\n",num[ed],w[ed]);
	DFS_Path(st,ed);
	for(unsigned i=0;i<ans.size();i++){
		if(i!=ans.size()-1){
			printf("%d ",ans[i]);	
		}else{
			printf("%d",ans[i]);
		}
	}
	return 0;
}
  1. Emergency AC code
    =======================
/*
	Name:L2-001紧急救援 
	Author: spencercjh
	Date:2017年11月15日15:41:14 
	Description:团体程序设计天梯赛-练习集
	reference:算法笔记 P380 
	key word:Dijkstra Dfs 
*/
#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<functional>
#include<numeric>
#include<stack>
using namespace std;
const int MAXV=510;
const int INF=0x3f3f3f3f;
int n,m,st,ed,G[MAXV][MAXV],weight[MAXV];
int d[MAXV],w[MAXV],num[MAXV],pre[MAXV];
bool vis[MAXV]= {false};
vector<int> ans;
void Dijkstra(int s) {
	//初始化边权、点权、边数数组 
	fill(d,d+MAXV,INF);
	fill(num,num+MAXV,0);
	fill(w,w+MAXV,0);
	//设置起点数据 
	d[s]=0;
	w[s]=weight[s];
	num[s]=1;
	//初始化路径数组 
	for(int i=0; i<n; i++) {
		pre[i]=i;
	}
	//Dijkstra外层循环 
	for(int i=0; i<n; i++) {
		int u=-1,MIN=INF;//u使d[u]最小,MIN存放该最小的d[u] 
		for(int j=0; j<n; j++) {//找到未访问的顶点中d[u]最小的 
			if(vis[j]==false&&d[j]<MIN) {
				u=j;
				MIN=d[j];
			}
		}
		if(u==-1) {//找不到小于INF的d[u],说明剩下的顶点和起点s不连通 
			return;
		}
		vis[u]=true;
		for(int v=0; v<n; v++) {
			if(vis[v]==false&&G[u][v]!=INF) {
				if(d[u]+G[u][v]<d[v]) {
					d[v]=d[u]+G[u][v];
					w[v]=w[u]+weight[v];
					num[v]=num[u];
					pre[v]=u;
				} else if(d[u]+G[u][v]==d[v]) {
					if(w[u]+weight[v]>w[v]) {
						w[v]=w[u]+weight[v];
						pre[v]=u;
					}
					num[v]+=num[u];
				}
			}
		}
	}
}
void DFS_Path(int s,int v) {
	if(v==s) {
		ans.push_back(s);
		return;
	}
	DFS_Path(s,pre[v]);
	ans.push_back(v);
}
int main() {
	scanf("%d %d %d %d",&n,&m,&st,&ed);
	for(int i=0; i<n; i++) {
		scanf("%d",&weight[i]);
	}
	fill(G[0],G[0]+MAXV*MAXV,INF);
	for(int i=0; i<m; i++) {
		int u,v;
		scanf("%d %d",&u,&v);
		scanf("%d",&G[u][v]);
		G[v][u]=G[u][v];
	}
	Dijkstra(st);
	printf("%d %d\n",num[ed],w[ed]);
	DFS_Path(st,ed);
//	for(unsigned i=0;i<ans.size();i++){
//		if(i!=ans.size()-1){
//			printf("%d ",ans[i]);	
//		}else{
//			printf("%d",ans[i]);
//		}
//	}
	return 0;
}

看输出样例你就能发现,其实1003 Emergency就是L2-001 紧急救援的阉割版,L2-001需要输出这条路径而它不用。
搞数据结构快半年了,说来惭愧这是我第一次真的一行行地去搞懂Dijkstra算法,熟记整个算法的框架。怪不得朋友说图论的这些题目也不是太难,因为用到这些算法的时候,大部分代码都是可以原封不动地复用的,你只需要去修改它的第二或者第三标尺。
在初始化各个数组的时候我用到了stl_fill,大家看了我的使用例子应该都懂怎么用了。可以用它去替代一个循环赋值或者是memset。额说实话我完全不懂memset……
《算法笔记》这本书真的很棒!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值