PTA-最短路径(1003/1018/1030/1072/1087)

10 篇文章 0 订阅
7 篇文章 0 订阅

1003 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 Specification:

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, C 1and C 2- 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 c 1, c 2​ 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 C 1to C 2 .

Output Specification:

For each test case, print in one line two numbers: the number of different shortest paths between C 1and C 2, 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

思路

这是一道典型的点权题,并且输出最短路径的条数。

#include<bits/stdc++.h>
using namespace std;
int n,m,c1,c2;
const int maxx=1000;
const int INF=1000000000;
struct node{
	int id,dis;
	node(int id,int dis){
		this->id=id;
		this->dis=dis;
	}
};
int weight[maxx],ton[maxx],num[maxx];
vector<node> vec[maxx];
bool visit[maxx]={false};
int d[maxx];
void dijkstra(int x){
	fill(d,d+maxx,INF);
	d[x]=0;
	num[x]=1;
	ton[x]=weight[x];
	for(int i=0;i<n;i++){
		int u=-1,minv=INF;
		for(int j=0;j<n;j++){
			if(!visit[j]&&d[j]<minv){
				u=j;
				minv=d[j];
			}
		}
		if(u<0) return ;
		visit[u]=true;
		for(int i=0;i<vec[u].size();i++){
			int v=vec[u][i].id;
			if(!visit[v]&&vec[u][i].dis+d[u]<=d[v]){
				d[v]=d[u]+vec[u][i].dis;
				ton[v]=max(ton[v],ton[u]+weight[v]);
				if(vec[u][i].dis+d[u]<d[v]) num[v]=num[u];
				else num[v]+=num[u];
			}
		}
	}
}
int main(){
	cin>>n>>m>>c1>>c2;
	int a,b,c;
	for(int i=0;i<n;i++){
		cin>>weight[i];
	}
	for(int i=0;i<m;i++){
		cin>>a>>b>>c;
		vec[a].push_back(node(b,c));
		vec[b].push_back(node(a,c));
	}
	dijkstra(c1);
	cout<<num[c2]<<' '<<ton[c2];
	return 0;
}

1018 Public Bike Management (30 分)

There is a public bike service in Hangzhou City which provides great convenience to the tourists from all over the world. One may rent a bike at any station and return it to any other stations in the city.

The Public Bike Management Center (PBMC) keeps monitoring the real-time capacity of all the stations. A station is said to be in perfect condition if it is exactly half-full. If a station is full or empty, PBMC will collect or send bikes to adjust the condition of that station to perfect. And more, all the stations on the way will be adjusted as well.

When a problem station is reported, PBMC will always choose the shortest path to reach that station. If there are more than one shortest path, the one that requires the least number of bikes sent from PBMC will be chosen.

The above figure illustrates an example. The stations are represented by vertices and the roads correspond to the edges. The number on an edge is the time taken to reach one end station from another. The number written inside a vertex S is the current number of bikes stored at S. Given that the maximum capacity of each station is 10. To solve the problem at S 3​
, we have 2 different shortest paths:PBMC -> S 1 -> S 3. In this case, 4 bikes must be sent from PBMC, because we can collect 1 bike from S 1 and then take 5 bikes to S 3, so that both stations will be in perfect conditions.PBMC -> S 2 -> S 3. This path requires the same time as path 1, but only 3 bikes sent from PBMC and hence is the one that will be chosen.

Input Specification:

Each input file contains one test case. For each case, the first line contains 4 numbers: C max (≤100), always an even number, is the maximum capacity of each station; N (≤500), the total number of stations; Sp , the index of the problem station (the stations are numbered from 1 to N, and PBMC is represented by the vertex 0); and M, the number of roads. The second line contains N non-negative numbers C i(i=1,⋯,N) where each C iis the current number of bikes at S i respectively. Then M lines follow, each contains 3 numbers: S i , S j , and T ij which describe the time T i taken to move betwen stations S i and S j​ . All the numbers in a line are separated by a space.

Output Specification:

For each test case, print your results in one line. First output the number of bikes that PBMC must send. Then after one space, output the path in the format: 0−>S 1 −>⋯−>S p. Finally after another space, output the number of bikes that we must take back to PBMC after the condition of S p is adjusted to perfect.
Note that if such a path is not unique, output the one that requires minimum number of bikes that we must take back to PBMC. The judge’s data guarantee that such a path is unique.

Sample Input:

10 3 3 5
6 7 0
0 1 1
0 2 1
0 3 3
1 3 1
2 3 1

Sample Output:

3 0->2->3 0

思路

dijkstra+dfs的题,这道题不能只用dijkstra做。
dijkstra负责找到所有的最短路径,dfs负责在这些最短路径中找到最优的解。
dfs对pre数组进行遍历,遍历从终点到起点的每一条路径,用条件加以判断,最终输出那条最优的路径。

#include<bits/stdc++.h>
using namespace std;
const int maxx=501;
const int INF=1000000000;
int c,n,s,m;
struct node {
	int id,dis;
	node(int id,int dis) {
		this->id=id;
		this->dis=dis;
	}
};
vector<node> vec[maxx];
vector<int> pre[maxx],temp,path;
int d[maxx],weight[maxx];
bool visit[maxx]= {false};
void dijkstra(int x) {
	fill(d,d+maxx,INF);
	d[x]=0;
	for(int i=0; i<=n; i++) {
		int u=-1,minv=INF;
		for(int j=0; j<=n; j++) {
			if(!visit[j]&&d[j]<minv) {
				minv=d[j];
				u=j;
			}
		}
		if(u<0) return ;
		visit[u]=true;
		for(int i=0; i<vec[u].size(); i++) {
			int v=vec[u][i].id;
			if(!visit[v]) {
				if(vec[u][i].dis+d[u]<d[v]) {
					d[v]=vec[u][i].dis+d[u];
					pre[v].clear();
					pre[v].push_back(u);
				} else if(vec[u][i].dis+d[u]==d[v]){
					pre[v].push_back(u);
				}
			}

		}
	}
}
int ansremain=INF,ansneed=INF;
void dfs(int x){
	if(x==0){
		temp.push_back(x);
		int remain=0,need=0;
		for(int i=temp.size()-1;i>=0;i--){
			int id=temp[i];
			if(weight[id]>0){
				remain+=weight[id];
			} else{
				if(remain>=abs(weight[id])){
					remain+=weight[id];
				} else{
					need+=abs(weight[id])-remain;
					remain=0;
				}
			}
		}
		if(need<ansneed){
			ansneed=need;
			path=temp;
			ansremain=remain;
		} else if(need==ansneed&&remain<ansremain){
			path=temp;
			ansremain=remain;
		}
		temp.pop_back();
		return ;
	}
	temp.push_back(x);
	for(int i=0;i<pre[x].size();i++){
		dfs(pre[x][i]);
	}
	temp.pop_back();
}
int main() {
	cin>>c>>n>>s>>m;
	for(int i=1; i<=n; i++) {
		cin>>weight[i];
		weight[i]-=c/2;
	}
	for(int i=0; i<m; i++) {
		int a,b,c;
		cin>>a>>b>>c;
		vec[a].push_back(node(b,c));
		vec[b].push_back(node(a,c));
	}
	dijkstra(0);
	dfs(s);
	cout<<ansneed<<' ';
	reverse(path.begin(),path.end());
	for(int i=0;i<path.size();i++){
		cout<<path[i];
		if(i!=path.size()-1) cout<<"->";
		else cout<<" ";
	}
	cout<<ansremain;
	return 0;
}

1030 Travel Plan (30 分)

A traveler’s map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting city and the destination. If such a shortest path is not unique, you are supposed to output the one with the minimum cost, which is guaranteed to be unique.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 4 positive integers N, M, S, and D, where N (≤500) is the number of cities (and hence the cities are numbered from 0 to N−1); M is the number of highways; S and D are the starting and the destination cities, respectively. Then M lines follow, each provides the information of a highway, in the format:
City1 City2 Distance Cost
where the numbers are all integers no more than 500, and are separated by a space.

Output Specification:

For each test case, print in one line the cities along the shortest path from the starting point to the destination, followed by the total distance and the total cost of the path. The numbers must be separated by a space and there must be no extra space at the end of output.

Sample Input:

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

Sample Output:

0 2 3 3 40

思路

这是一道最短路与边权结合的题,并且要求输出最优路径,可以使用dfs递归输出,也可以直接在dijkstra中输出。

#include<bits/stdc++.h>
using namespace std;
const int maxx=1000;
const int INF=1000000000;
struct node{
	int id,dis,weight;
	node(int id,int dis,int weight){
		this->id=id;
		this->dis=dis;
		this->weight=weight;
	}
};
vector<node> vec[maxx];
vector<int> ans[maxx];
int n,m,s,q;
int d[maxx],ton[maxx];
bool visit[maxx];
void dijkstra(int x){
	fill(d,d+maxx,INF);
	d[x]=0;
	ans[x].push_back(x);
	for(int i=0;i<n;i++){
		int u=-1,minv=INF;
		for(int j=0;j<n;j++){
			if(!visit[j]&&d[j]<minv){
				u=j;
				minv=d[j];
			}
		}
		if(u<0) return ;
		visit[u]=true;
		for(int i=0;i<vec[u].size();i++){
			int v=vec[u][i].id;
			if(!visit[v]){
				if(vec[u][i].dis+d[u]<d[v]){
					d[v]=vec[u][i].dis+d[u];
					ton[v]=ton[u]+vec[u][i].weight;
					ans[v].clear();
					ans[v].insert(ans[v].end(),ans[u].begin(),ans[u].end());
					ans[v].push_back(v);
				} else if(vec[u][i].dis+d[u]==d[v]){
					if(ton[u]+vec[u][i].weight<ton[v]){
						ton[v]=ton[u]+vec[u][i].weight;
						ans[v].clear();
						ans[v].insert(ans[v].end(),ans[u].begin(),ans[u].end());
						ans[v].push_back(v);
					}
				}
			}
		}
	}
}
int main()
{
	cin>>n>>m>>s>>q;
	for(int i=0;i<m;i++){
		int a,b,c,e;
		cin>>a>>b>>c>>e;
		vec[a].push_back(node(b,c,e));
		vec[b].push_back(node(a,c,e));
	}
	dijkstra(s);
	for(int i=0;i<ans[q].size();i++){
		cout<<ans[q][i]<<' ';
	}
	cout<<d[q]<<' '<<ton[q];
	return 0;
}

1072 Gas Station (30 分)

A gas station has to be built at such a location that the minimum distance between the station and any of the residential housing is as far away as possible. However it must guarantee that all the houses are in its service range.

Now given the map of the city and several candidate locations for the gas station, you are supposed to give the best recommendation. If there are more than one solution, output the one with the smallest average distance to all the houses. If such a solution is still not unique, output the one with the smallest index number.

Input Specification:

Each input file contains one test case. For each case, the first line contains 4 positive integers: N (≤103 ), the total number of houses; M (≤10), the total number of the candidate locations for the gas stations; K (≤10 4 ), the number of roads connecting the houses and the gas stations; and D S , the maximum service range of the gas station. It is hence assumed that all the houses are numbered from 1 to N, and all the candidate locations are numbered from G1 to GM.

Then K lines follow, each describes a road in the format

P1 P2 Dist
where P1 and P2 are the two ends of a road which can be either house numbers or gas station numbers, and Dist is the integer length of the road.

Output Specification:

For each test case, print in the first line the index number of the best location. In the next line, print the minimum and the average distances between the solution and all the houses. The numbers in a line must be separated by a space and be accurate up to 1 decimal place. If the solution does not exist, simply output No Solution.

Sample Input 1:

4 3 11 5
1 2 2
1 4 2
1 G1 4
1 G2 3
2 3 2
2 G2 1
3 4 2
3 G3 2
4 G1 3
G2 G1 1
G3 G2 2

Sample Output 1:

G1
2.0 3.3

Sample Input 2:

2 1 2 10
1 G1 9
2 G1 20

Sample Output 2:

No Solution

思路

这道题最难的点在于读题,能否读懂挑选离距离最近的点的距离值最大的结点输出,还有加油站可能有10个,所以截断字符串a.substr(1)后再使用stoi才能将10正确提取出来。

#include<bits/stdc++.h>
using namespace std;
const int maxx=1020;
const int INF=1000000000;
int n,m,k,road;
struct node{
	int id,dis;
	node(int id,int dis){
		this->id=id;
		this->dis=dis;
	}
};
vector<node> vec[maxx];
bool visit[maxx]={false};
int d[maxx];
void dijkstra(int x){
	fill(d,d+maxx,INF);
	d[x]=0;
	for(int i=0;i<n+m;i++){
		int u=-1,minv=INF;
		for(int j=1;j<=n+m;j++){
			if(!visit[j]&&d[j]<minv){
				minv=d[j];
				u=j;
			}
		}
		if(u<0) return ;
		visit[u]=true;
		for(int i=0;i<vec[u].size();i++){
			int v=vec[u][i].id;
			if(d[u]+vec[u][i].dis<d[v]){
				d[v]=d[u]+vec[u][i].dis;
			}
		}
	}
}
int main()
{
	cin>>n>>m>>k>>road;
	for(int i=0;i<k;i++){
		string a,b;
		int c;
		int x,y;
		cin>>a>>b>>c;
		if(a[0]=='G') x=stoi(a.substr(1))+n;
		else x=stoi(a);
		if(b[0]=='G') y=stoi(b.substr(1))+n;
		else y=stoi(b);
		vec[x].push_back(node(y,c));
		vec[y].push_back(node(x,c));
	}
	double allavg=0,alldis=0;
	int allid=0;
	for(int i=n+1;i<=n+m;i++){
		fill(visit,visit+maxx,false);
		dijkstra(i);
		bool pan=false;
		double inavg=0,indis=INF;
		for(int j=1;j<=n;j++){
			if(d[j]>road){
				pan=true;
				break;
			}
			inavg+=1.0*d[j]/n;
			if(d[j]<indis){
				indis=d[j];
			}
		}
		if(pan) continue;
		if(indis>alldis){
			allid=i;
			alldis=indis;
			allavg=inavg;
		} else if(indis==alldis&&inavg<allavg){
			allid=i;
			allavg=inavg;
		}
	}
	if(allid==0){
		cout<<"No Solution";
	}else{
		printf("G%d\n%.1f %.1f", allid - n, alldis, allavg);
	}
	return 0;
}

1087 All Roads Lead to Rome (30 分)

Indeed there are many different tourist routes from our city to Rome. You are supposed to find your clients the route with the least cost while gaining the most happiness.

Input Specification:
Each input file contains one test case. For each case, the first line contains 2 positive integers N (2≤N≤200), the number of cities, and K, the total number of routes between pairs of cities; followed by the name of the starting city. The next N−1 lines each gives the name of a city and an integer that represents the happiness one can gain from that city, except the starting city. Then K lines follow, each describes a route between two cities in the format City1 City2 Cost. Here the name of a city is a string of 3 capital English letters, and the destination is always ROM which represents Rome.

Output Specification:
For each test case, we are supposed to find the route with the least cost. If such a route is not unique, the one with the maximum happiness will be recommanded. If such a route is still not unique, then we output the one with the maximum average happiness – it is guaranteed by the judge that such a solution exists and is unique.

Hence in the first line of output, you must print 4 numbers: the number of different routes with the least cost, the cost, the happiness, and the average happiness (take the integer part only) of the recommanded route. Then in the next line, you are supposed to print the route in the format City1->City2->…->ROM.

Sample Input:
6 7 HZH
ROM 100
PKN 40
GDN 55
PRS 95
BLN 80
ROM GDN 1
BLN ROM 1
HZH PKN 1
PRS ROM 2
BLN HZH 2
PKN GDN 1
HZH PRS 1
Sample Output:
3 3 195 97
HZH->PRS->ROM

思路

重量相同后再次比较再比较平均值;
在审清题意看清楚优先级的情况下,这道题还是比较基础。

#include<bits/stdc++.h>
using namespace std;
const int maxx=1000;
const int INF=1000000000;
int n,k;
string beg;
map<string,int> strToInt;
map<int,string> intToStr;
struct node {
	int id,dis;
	node(int id,int dis) {
		this->id=id;
		this->dis=dis;
	}
};
vector<node> vec[maxx];
vector<int> ans[maxx];
int weight[maxx],ton[maxx];
bool visit[maxx]= {false};
int num=1;
int exchange(string str) {
	for(auto it=strToInt.begin(); it!=strToInt.end(); it++) {
		if(it->first==str) return it->second;
	}
	strToInt[str]=num;
	intToStr[num]=str;
	return num++;
}
int d[maxx];
int tot[maxx];
void dijkstra(int x) {
	fill(d,d+maxx,INF);
	d[x]=0;
	tot[x]=1;
	ans[x].push_back(x);
	for(int i=0; i<num; i++) {
		int u=-1,minv=INF;
		for(int j=0; j<num; j++) {
			if(!visit[j]&&d[j]<minv) {
				u=j;
				minv=d[j];
			}
		}
		visit[u]=true;
		if(u<0) return ;
		for(int i=0; i<vec[u].size(); i++) {
			int v=vec[u][i].id;
			if(!visit[v]) {
				if(d[u]+vec[u][i].dis<d[v]) {
					d[v]=vec[u][i].dis+d[u];
					ans[v].clear();
					ans[v].insert(ans[v].end(),ans[u].begin(),ans[u].end());
					ans[v].push_back(v);
					tot[v]=tot[u];
					ton[v]=ton[u]+weight[v];
				} else if(d[u]+vec[u][i].dis==d[v]) {
					if(ton[u]+weight[v]>ton[v]) {
						ans[v].clear();
						ans[v].insert(ans[v].end(),ans[u].begin(),ans[u].end());
						ans[v].push_back(v);
						ton[v]=ton[u]+weight[v];
					} else if(ton[u]+weight[v]==ton[v]) {
						if((ton[u]+weight[v])*1.0/(ans[u].size())>ton[v]*1.0/(ans[v].size()-1)) {
							ans[v].clear();
							ans[v].insert(ans[v].end(),ans[u].begin(),ans[u].end());
							ans[v].push_back(v);
							ton[v]=ton[u]+weight[v];
						}
					}
					tot[v]+=tot[u];
				}
			}
		}
	}
}
int main() {
	cin>>n>>k>>beg;
	string a,b;
	int w;
	weight[0]=0;
	strToInt[beg]=0;
	intToStr[0]=beg;
	for(int i=1; i<n; i++) {
		cin>>a>>w;
		int id=exchange(a);
		weight[id]=w;
	}
	for(int i=0; i<k; i++) {
		cin>>a>>b>>w;
		int id1=exchange(a);
		int id2=exchange(b);
		vec[id1].push_back(node(id2,w));
		vec[id2].push_back(node(id1,w));
	}
	dijkstra(strToInt[beg]);
	int end=strToInt["ROM"];
	cout<<tot[end]<<' '<<d[end]<<' '<<ton[end]<<' '<<ton[end]/(ans[end].size()-1)<<endl;
	for(int i=0; i<ans[end].size(); i++) {
		int id=ans[end][i];
		cout<<intToStr[id];
		if(i!=ans[end].size()-1) cout<<"->";
	}
	return 0;
}

总结

做题时先采用dijkstra,如果发现有个别点过不去,可以利用dijkstra+dfs做题,将优先级情况单独对所有最短路径集合进行分析。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新西兰做的饭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值