哈密顿回路
??给定一个无向图,由指定的起点前往指定的终点,途中经过的所有其他顶点且只经过一次,成为哈密顿路径,闭合的哈密顿路径(起点和终点相同)成为哈密顿回路(Hamiltonian Cycle)。设计一个回溯算法求无向图的哈密顿回路。
输入格式
??第一行以空格隔开输入两个整数:n(1≤n≤10)表示顶点的个数,以及e(1≤e≤n*(n+1)/2)表示边的条数。接下来e行,每一行以空格隔开输入两个整数,表示两个顶点间有一条边(顶点编号范围1~n)。最后一行输入一个整数s表示指定的起点。
输出格式
??输出所有的哈密顿回路(按编号大小升序排列),每一条回路在一行,输出该条回路的全部顶点编号,且每一条回路以"Path #: "开始(#是路径编号,从1开始),并以空格隔开。
输入样例
5 7
2 1
3 1
4 1
4 2
5 2
5 3
5 4
1
输出样例
Path 1: 1 2 4 5 3 1
Path 2: 1 3 5 2 4 1
Path 3: 1 3 5 4 2 1
Path 4: 1 4 2 5 3 1
解题思路
思路
??使用二维数组储存无向图。每次以当前顶点为起点,从小到大遍历所有顶点,如果能够到达且该点未访问就记录在路径中。如果访问至起点则判断当前路径长度即经过的顶点数是否等于总顶点数量,若相等就依次输出路径的顶点,否则返回上一个顶点并回溯到访问前的状态继续遍历,直到遍历完所有顶点程序结束。
解题代码
定义变量
const int maxn = 15;
bool Graph[maxn][maxn] = { false };
bool vis[maxn] = { false };
int n, e;
int s;
vector<int>path;
int cnt = 0;
数据读入
cin >> n >> e;
while (e--)
{
int v1, v2;
cin >> v1 >> v2;
Graph[v1][v2] = Graph[v2][v1] = true;
}
cin >> s;
path.push_back(s);
递归实现
void dfs(int v, int length)
{
if (length == n && v == s)
{
num++;
cout << "Path " << cnt << ":";
for (auto x : path)
{
cout << " " << x;
}
cout << endl;
return;
}
for (int i = 1; i <= n; i++)
{
if (!vis[i] && Graph[v][i])
{
vis[i] = true;
path.push_back(i);
dfs(i, length+1);
path.pop_back();
vis[i] = false;
}
}
}
整体代码
#include <iostream>
#include <vector>
using namespace std;
const int maxn = 15;
bool Graph[maxn][maxn] = { false };
bool vis[maxn] = { false };
int n, e;
int s;
vector<int>path;
int cnt = 0;
void dfs(int v, int length)
{
if (length == n && v == s)
{
cnt++;
cout << "Path " << cnt << ":";
for (int x : path)
{
cout << " " << x;
}
cout << endl;
return;
}
for (int i = 1; i <= n; i++)
{
if (!vis[i] && Graph[v][i])
{
vis[i] = true;
path.push_back(i);
dfs(i, length+1);
path.pop_back();
vis[i] = false;
}
}
}
int main()
{
cin >> n >> e;
while (e--)
{
int v1, v2;
cin >> v1 >> v2;
Graph[v1][v2] = Graph[v2][v1] = true;
}
cin >> s;
path.push_back(s);
dfs(s, 0);
return 0;
}
|