那为什么vis数组的判断条件是不同的
时间: 2023-11-18 22:03:42 浏览: 60
在两个循环中,`vis` 数组的判断条件确实是不同的。这是因为这两段代码所实现的算法不同。
在第一个循环中,使用的是 Dijkstra 算法,`vis` 数组用于记录已经访问过的节点。初始时,所有节点都未访问过,所以判断条件是 `!vis[i]`,表示当前节点未被访问。
而在第二个循环中,使用的可能是另一种算法(如贪心算法或者其他寻找最短路径的算法),`vis` 数组同样用于记录已经访问过的节点。初始时,起始节点 `t1` 已经被访问过,所以判断条件是 `vis[j]==0`,表示当前节点未被访问。
因此,虽然 `vis` 数组的含义相同,但在不同的算法或不同的实现中,其判断条件可能会有所不同。
相关问题
写出满足如下要求的C++代码:分支限界法解决子集和数的问题,输入格式: 第一行为一个不超过200的正整数n,表示总集规模; 第二行是正整数M,表示子集的和数; 第三行是总集中n个正整数,中间用空格隔开。 输出格式: 如果有答案,则输出所有满足条件的子集(用可变长度数组表示符合条件的一个子集,子集中元素表示被选中的数值的下标); 如果没有答案,则输出“no solution!”。
以下是满足要求的C++代码:
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 200;
struct Node {
int sum; // 子集和
vector<int> path; // 子集
};
int n, m;
int a[MAXN + 5];
bool vis[MAXN + 5];
bool cmp(Node a, Node b) {
return a.sum < b.sum;
}
void dfs(int u, int sum, vector<int> path, vector<Node>& ans) {
if (sum > m) return; // 剪枝
if (u > n) {
if (sum == m) {
Node node = {sum, path};
ans.push_back(node); // 加入答案
}
return;
}
dfs(u + 1, sum, path, ans); // 不选当前数
path.push_back(u);
dfs(u + 1, sum + a[u], path, ans); // 选当前数
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
vector<int> path;
vector<Node> ans;
dfs(1, 0, path, ans);
if (ans.empty()) {
cout << "no solution!\n";
} else {
sort(ans.begin(), ans.end(), cmp);
for (int i = 0; i < ans.size(); i++) {
for (int j = 0; j < ans[i].path.size(); j++) {
cout << ans[i].path[j] << " ";
}
cout << "\n";
}
}
return 0;
}
```
解释一下代码的思路:
- 首先输入总集规模n和子集和数M,以及n个正整数a[i]。
- 然后定义一个节点结构体Node,包含子集和sum和子集path(用vector表示)。
- 定义一个dfs函数,其中u表示当前考虑到第几个数,sum表示当前子集的和,path表示当前子集的路径,ans表示答案集合。
- 在dfs函数中,先判断是否超过子集和,如果超过则剪枝;如果已经考虑完了所有数,判断当前子集和是否为M,如果是则将当前子集加入答案集合。
- 接着分别考虑选或不选当前数,进行递归搜索。
- 最后在主函数中调用dfs函数,如果答案集合为空,输出"no solution!";否则对答案集合进行排序,依次输出每个子集的路径。
求无向图是否为一颗树,请写出c语言代码实现
以下是使用深度优先搜索(DFS)判断无向图是否为一棵树的 C 语言代码实现:
```c
#include <stdio.h>
#include <stdbool.h>
#define MAXN 10000 // 最大节点数
int head[MAXN], nxt[MAXN*2], ver[MAXN*2]; // 邻接表存储图
bool vis[MAXN]; // 标记节点是否被访问过
int fa[MAXN]; // 记录每个节点的父节点
int cnt = 0; // 边数
int n; // 节点数
// 添加一条边
void add_edge(int u, int v) {
nxt[++cnt] = head[u];
ver[cnt] = v;
head[u] = cnt;
}
// DFS 遍历整个无向图,判断是否为一棵树
bool dfs(int u, int father) {
fa[u] = father; // 记录父节点
vis[u] = true; // 标记已经访问过
for (int i = head[u]; i; i = nxt[i]) { // 遍历与当前节点相邻的节点
int v = ver[i];
if (vis[v] && v != father) { // 如果当前节点已经被访问过,且不是父节点
return false; // 发现环路,不是一棵树
}
if (!vis[v]) { // 如果当前节点没有被访问过
if (!dfs(v, u)) { // 递归调用 DFS
return false; // 发现环路,不是一棵树
}
}
}
return true; // 没有发现环路,是一棵树
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n-1; i++) { // 读入边
int u, v;
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
if (dfs(1, 0) && !vis[n]) { // 从节点 1 开始 DFS,判断是否为一棵树
printf("Yes\n");
} else {
printf("No\n");
}
return 0;
}
```
代码中使用邻接表存储无向图,其中 `head[u]` 存储与节点 `u` 相连的第一条边在数组中的位置,`nxt[i]` 存储与第 `i` 条边同起点的下一条边在数组中的位置,`ver[i]` 存储第 `i` 条边的终点。
在 DFS 遍历过程中,使用数组 `vis` 标记节点是否被访问过,使用数组 `fa` 记录每个节点的父节点。如果发现当前节点已经被访问过,且不是父节点,则说明发现了环路,不是一棵树。
最后判断从节点 1 开始 DFS 是否能够访问到所有节点,并且不发现环路,如果满足条件,则说明这个无向图是一棵树。