4014-基于邻接表的长度为k的简单路径的求解(C++,附思路)

描述

一个连通图采用邻接表作为存储结构。设计一个算法,判断无向图中任意给定的两点是否存在一条长度为k的简单路径。

输入

多组数据,每组m+3数据行。第一行有两个数字n,m和k,代表有n个顶点,m条边和长度k。第二行有n个字符,代表n个顶点的编号。第三行到第m+2行每行有两个字符h和p,代表边依附的两个顶点。每条边的长度为1。第m+3行有两个字符d和f,代表需要判断的两个字符。

输出

每组数据输出一行。若存在路径输出“YES”,反之输出“NO”。

输入样例 1 

3 2 2
abc
ab
bc
ac
4 2 5
bcsw
bs
sw
bw
0 0 0

输出样例 1

YES
NO

思路:

邻接表的建立等基本操作在这篇文章里有写,所以下面就不赘述了~

4003基于邻接表的新顶点的增加(C++,附详细解析)_鹤天寻的博客-CSDN博客icon-default.png?t=LA92https://blog.csdn.net/qq_54416938/article/details/121582300?spm=1001.2014.3001.5501

用到了一个全局map,map用来存储每个节点所对应的序号节点,比如说abc来建立邻接表,a对应1,b对应2,c对应3,那么就把他们都存在map里,之后再用这个输入的字符串初始化邻接表。

接着逐个输入字符串,借助map的迭代器来找到当前节点对应在邻接表里的序号,建立邻接表。

之后就是寻找路径了,设置一个计步器len,每走过一步就让len++,若当前走完了,就以最后的节点为起点在邻接表里继续遍历,直到到达目标节点为止,比较len和k的值,相等就是YES,否则就输出NO。

我认为精彩之处在于

            pos = GetPos(p->data);
            p = &alg.VList[pos];

这两句代码以及借助map的思想,这样就达到了“循环遍历”的效果。

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<stack>
#include<set>
#include<map>
using namespace std;
map<char, int> mp;
typedef struct LNode
{
	char data;
	struct LNode* next;
}*linklist, LNode;
typedef struct
{
	int arcnum;
	int vexnum;
	linklist VList;
}ALGraph;
void Create(ALGraph& alg, int n, int m)
{
	alg.arcnum = m;
	alg.vexnum = n;
	alg.VList = new LNode[n + 1];
	string ves;
	cin >> ves;

	for (int i = 0; i < ves.length(); i++)
		mp[ves[i]] = i + 1;
	int j = 0;
	for (int i = 1; i <= n; i++)
	{
		alg.VList[i].data = ves[j++];
		alg.VList[i].next = NULL;
	}
	map<char, int>::iterator it = mp.begin();
	for (int i = 0; i < m; i++)
	{
		string t;
		cin >> t;
		linklist p = new LNode;
		p->data = t[1];
		while (it != mp.end())
		{
			if (it->first == t[0])
			{
				p->next = alg.VList[it->second].next;
				alg.VList[it->second].next = p;
				break;
			}
			it++;
		}
	}
}
int GetPos(char c)
{
	map<char, int>::iterator it = mp.begin();
	int pos = 0;
	while (it != mp.end())
	{
		if (it->first == c)
		{
			pos = it->second;
			break;
		}
		it++;
	}
	return pos;
}
void Find(ALGraph alg,int k)
{
	string t;
	cin >> t;
	int pos = GetPos(t[0]);
	linklist p = &alg.VList[pos];
	int len = 0;
	while (p)
	{
		len++;
		p = p->next;
		if (p->data == t[1])
			break;
		else
		{
			pos = GetPos(p->data);
			p = &alg.VList[pos];
		}
	}
	if (len != k)
		cout << "NO" << endl;
	else
		cout << "YES" << endl;
}
int main()
{
	int m, n, k;
	while (cin >> n >> m >>k&& m != 0 && n != 0&&k!=0)
	{
		ALGraph a;
		Create(a, n, m);
		Find(a, k);
	}
	return 0;
}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是基于Dijsktra算法的最短路径求解C++代码示例: ```c++ #include <iostream> #include <vector> #include <queue> #include <limits.h> using namespace std; const int MAXN = 1005; // 最大节点数 struct Edge { int to, w; Edge(int _to, int _w) : to(_to), w(_w) {} }; vector<Edge> G[MAXN]; // 邻接表 int d[MAXN]; // 存储最短路径长度 bool vis[MAXN]; // 标记节点是否已访问 void dijkstra(int s) { fill(d, d + MAXN, INT_MAX); // 初始化距离为无穷大 fill(vis, vis + MAXN, false); // 初始化所有节点为未访问状态 d[s] = 0; // 起点距离为0 priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q; // 小根堆 q.push(make_pair(0, s)); // 将起点加入堆 while (!q.empty()) { int u = q.top().second; q.pop(); if (vis[u]) continue; vis[u] = true; for (auto &e: G[u]) { int v = e.to; if (d[v] > d[u] + e.w) { d[v] = d[u] + e.w; if (!vis[v]) q.push(make_pair(d[v], v)); } } } } int main() { int n, m, s; cin >> n >> m >> s; // n为节点数,m为边数,s为起点编号 for (int i = 0; i < m; ++i) { int u, v, w; cin >> u >> v >> w; G[u].push_back(Edge(v, w)); // 存储有向 } dijkstra(s); for (int i = 1; i <= n; ++i) { if (d[i] == INT_MAX) cout << "INF" << endl; // 输出无穷大 else cout << d[i] << endl; } return 0; } ``` 在这个示例中,我们使用了邻接表存储,并使用了小根堆来优化Dijsktra算法的时间复杂度。在主函数中,我们首先输入节点数、边数和起点编号,然后读入边的信息,存储为邻接表。最后调用`dijkstra()`函数求解最短路径,并输出结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值