洛谷P1529 回家 Bessie Come Home题解

本蒟蒻的第二篇题解

原题链接

相信你已经读完了题目,可能会觉得这题目有点恶心,感觉还要什么高级的字符串算法,其实并不难,只要会把字符串转换成整型,再注意一些细节,相信这道题对你来说就好像模板一样简单了

甚至可以一遍过……

那么,问题来了:我们该怎样巧妙地储存这些农场之间的路径呢?

各位可以先思考一下,我们平时用SPFA算法时,是怎样储存路径的?

相信各位大佬闭着眼睛都能打出来

int u, v, w;
scanf("%d%d%d", &u, &v, &w);
g[u].push_back(node{u, v, w});//储存到动态数组里面,无向图储存
g[v].push_back(node{v, u, w});

这道题就是把u和v改成了字符!

而我们又能够熟悉地打出将字符转化成整型的代码:

like this:

char a, b;
int s;
cin >> a >> b >> s;
int u = (int)(a - 64);//A的ascii值是65,这里直接减64,z的ascii值是122,注意数组的大小至少为58
int v = (int)(b - 64);

所以输入的问题我们就迎刃而解了

for(int i = 1; i <= m; i++) {
	char a, b;
	int s;
	cin >> a >> b >> s;
	int u = (int)(a - 64);
	int v = (int)(b - 64);
	g[u].push_back(node{u, v, s});
	g[v].push_back(node{v, u, s});
}

那么我们先不考虑只有大写字母的牧场中有一只母牛,假设每一种字母当中都有母牛

而每一只母牛的终点都是Z,这道题又是无向图,所以我们就把Z当做起点去遍历每一个点,得到每一个点到Z点的距离

就像这样:

void SPFA(int s) {
	for(int i = 1; i <= 58; i++) {//初始化
		dis[i] = INT_MAX;
	}
	dis[s] = 0;
	queue<int> q;
	q.push(s);
	while(!q.empty()) {//SPFA模板,不再解释
		int tmp = q.front();
		q.pop();
		vis[tmp] = 0;
		for(int i = 0; i < g[tmp].size(); i++) {
			int V = g[tmp][i].v, W = g[tmp][i].w;
			if(dis[V] > dis[tmp] + W) {
				dis[V] = dis[tmp] + W;
				if(!vis[V]) {
					q.push(V);
					vis[V] = 1;
				}
			}
		}
	}
}

但还没完,还是要记住只有大写字母的牧场中有一只母牛,所以输出时只能从1循环到25(Z是起点,所以不能遍历到26),找到最小值并输出

代码:

for(int i = 1; i <= 25; i++) {//只遍历大写字母且不遍历26
	if(dis[i] < Min) {//更新最小值
		Min = dis[i];
		index = i;
	}
}
cout << (char)(index + 64) << " " << dis[index];//输出时还原字母

然后这道题就被你切掉了~~~

虽然我知道,把上面的代码串起来再增加一些细节就能过,可以不用贴代码,但我爱你们啊!

所以……

代码时刻

#include<bits/stdc++.h>
using namespace std;
#define SF scanf
#define PF printf
int dis[105], vis[105];
struct node {
	int u, v, w;
};
vector<node> g[105];
void SPFA(int s) {
	for(int i = 1; i <= 58; i++) {
		dis[i] = INT_MAX;
	}
	dis[s] = 0;
	queue<int> q;
	q.push(s);
	while(!q.empty()) {
		int tmp = q.front();
		q.pop();
		vis[tmp] = 0;
		for(int i = 0; i < g[tmp].size(); i++) {
			int V = g[tmp][i].v, W = g[tmp][i].w;
			if(dis[V] > dis[tmp] + W) {
				dis[V] = dis[tmp] + W;
				if(!vis[V]) {
					q.push(V);
					vis[V] = 1;
				}
			}
		}
	}
}
int main() {
	int m;
	SF("%d", &m);
	for(int i = 1; i <= m; i++) {
		char a, b;
		int s;
		cin >> a >> b >> s;
		int u = (int)(a - 64);
		int v = (int)(b - 64);
		g[u].push_back(node{u, v, s});
		g[v].push_back(node{v, u, s});
	}
	SPFA(26);
	int index, Min = INT_MAX;
	for(int i = 1; i <= 25; i++) {
		if(dis[i] < Min) {
			Min = dis[i];
			index = i;
		}
	}
	cout << (char)(index + 64) << " " << dis[index];
	return 0;
}

拒绝复制,从我做起

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值