图的深搜
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 100;
int G[maxn][maxn], vis[maxn];
int n, m;
vector<int> ans;
void dfs(int start) {
vis[start] = 1;
ans.push_back(start);
for(int i = 0; i < n; i++)
if(!vis[i] && G[start][i]) dfs(i);
}
int main()
{
printf("please enter the number of nodes and sides:\n");
scanf("%d", &n); scanf("%d", &m);
int u, v, val; memset(G, 0, sizeof(G)); //首先要清空临接矩阵
printf("crate the matrix:\n");
for(int i = 0; i < m; i++) { //建立临接矩阵
scanf("%d%d%d", &u, &v, &val);
G[u][v] = val;
// G[v][u] = val; //如果是无向图就得加上这句话
}
printf("enter the start:\n");
int start; scanf("%d", &start);
ans.clear(); //首先要清空ans里面的残留数据
memset(vis, 0, sizeof(vis));
dfs(start);
printf("the search path:\n");
printf("%d", ans[0]);
for(int i = 1; i < ans.size(); i++) printf("-->%d", ans[i]);
printf("\n");
return 0;
}
当某种情况需要的节点过多,必须直接开较大的数组,如果依然用二维数组来保存临接矩阵,这时就会出现一下的异常:
所以采用如下方法将数组变成用vector的一维数组
/*对于节点过多的情况,直接开数组来表示临接矩阵就不可行了,
而采用临接链表的方式查找一条边又很麻烦,一下代码是基本就是临接链表做了一点改进*/
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 10000000 + 5;
struct Side { //如果是有权图的话需要用结构体来存储权值
int u, v, val;
Side(int u = 0, int v = 0, int val = 0) : u(u), v(v), val(val) {}
};
vector<Side> sideVec; //用这个vec来存储边
vector<int> G[maxn]; /*可以把这个vec看成类似临接链表中的主链表,也可以写成vector<vector<int> > G;能提升运行效率,因为初始化vector数组也需要大量时间,注意两个'>'要分开,不然编译器无法识别*/
vector<int> ans; //用来存放节点访问顺序
int n, m, start; //节点的个数以及边的数量
void addSide(int a, int b, int cos) {
sideVec.push_back(Side(a, b, cos));
int dex = sideVec.size() - 1;
G[a].push_back(dex); //只保存在sideVec中的下标而不是节点b是为了能够访问到权值
}
void dfs(int start, bool vis[]) {
vis[start] = true;
for(int i = 0; i < G[start].size(); i++) {
int idex = G[start][i];
int v = sideVec[idex].v; //v是与start相邻的节点
if(!vis[v]) {ans.push_back(v); dfs(v, vis);}
}
}
int main()
{
printf("enter the number of nodes and sides\n");
scanf("%d%d", &n, &m);
int u, v, val;
printf(("create the matrix\n"));
for(int i = 0; i < m; i++) { //先创建图的整体结构
scanf("%d%d%d", &u, &v, &val);
addSide(u, v, val); //增加边
// addSide(v, u, val); //暂且先假设为无向图
}
printf("enter the start node:\n");
scanf("%d", &start);
ans.clear();
ans.push_back(start);
bool vis[n + 5];
memset(vis, 0, sizeof(vis));
dfs(start, vis);
printf("the search path:\n");
printf("%d", ans[0]);
for(int i = 1; i < ans.size(); i++) printf("-->%d", ans[i]);
printf("\n");
return 0;
}
图的广搜
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 100;
int G[maxn][maxn], vis[maxn];
int n, m; //图的节点和边
vector<int> ans;
void bfs(int start) {
queue<int> q;
q.push(start);
memset(vis, 0, sizeof(vis)); vis[start] = 1;
int u;
while(!q.empty()) {
u = q.front();
ans.push_back(u);
q.pop();
for(int i = 0; i < n; i++)
if(!vis[i] && G[u][i]) {q.push(i); vis[i] = 1;}
}
}
int main()
{
printf("please enter the number of nodes and sides:\n");
scanf("%d", &n); scanf("%d", &m);
int u, v, val; memset(G, 0, sizeof(G)); //首先要清空临接矩阵
printf("crate the matrix:\n");
for(int i = 0; i < m; i++) { //建立临接矩阵
scanf("%d%d%d", &u, &v, &val);
G[u][v] = val;
G[v][u] = val; //如果是无向图就得加上这句话
}
printf("enter the start:\n");
int start; scanf("%d", &start);
ans.clear(); //首先要清空ans里面的残留数据
bfs(start);
printf("the search path:\n");
printf("%d", ans[0]);
for(int i = 1; i < ans.size(); i++) printf("-->%d", ans[i]);
printf("\n");
return 0;
}
对于处理数量较大节点的BFS同样如下:
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = 10000000 + 5;
struct Side { //如果是有权图的话需要用结构体来存储权值
int u, v, val;
Side(int u = 0, int v = 0, int val = 0) : u(u), v(v), val(val) {}
};
vector<Side> sideVec; //用这个vec来存储边
vector<int> G[maxn]; //可以把这个vec看成类似临接链表中的主链表
vector<int> ans; //用来存放节点访问顺序
int n, m, start; //节点的个数以及边的数量
void addSide(int a, int b, int cos) {
sideVec.push_back(Side(a, b, cos));
int dex = sideVec.size() - 1;
G[a].push_back(dex); //只保存在sideVec中的下标而不是节点b是为了能够访问到权值
}
void bfs(int start, bool vis[]) {
queue<int> q;
q.push(start); vis[start] = true;
int u;
while(!q.empty()) {
u = q.front(); q.pop();
for(int i = 0; i < G[u].size(); i++) {
int idex = G[u][i];
int v = sideVec[idex].v;
if(!vis[v]) {
ans.push_back(v);
q.push(v);
vis[v] = true;
}
}
}
}
int main()
{
printf("enter the number of nodes and sides\n");
scanf("%d%d", &n, &m);
int u, v, val;
printf(("create the matrix\n"));
for(int i = 0; i < m; i++) { //先创建图的整体结构
scanf("%d%d%d", &u, &v, &val);
addSide(u, v, val); //增加边
// addSide(v, u, val); //暂且先假设为无向图
}
printf("enter the start node:\n");
scanf("%d", &start);
ans.clear();
ans.push_back(start);
bool vis[n + 5];
memset(vis, 0, sizeof(vis));
bfs(start, vis);
printf("the search path:\n");
printf("%d", ans[0]);
for(int i = 1; i < ans.size(); i++) printf("-->%d", ans[i]);
printf("\n");
return 0;
}
接下来是例题,uvaOJ1599。上面处理大量节点的DFS/BFS代码基本来自于此题,照搬RuJia
题目描述:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=51300
代码如下:
/*这道题可以用BFS解决,但是记录父节点的方法不能保证打印出来的路径字典序最小,所以解决方法是从终点倒着BFS,得到每个节点到终点的最小距离d[i](注意此时的图要看作无向无权图)。然后就可从起点开始BFS,到达一个节点时要保证d值减少1*/
#include <iostream>
#include <cstdio>
#include <vector> //因为直接开数组占用的内存会过大而无法运行,所以使用vector
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100000 + 5;
const int INF = 1000000000;
struct Side {
int u, v, val;
Side(int u = 0, int v = 0, int val = 0) : u(u), v(v), val(val) {}
};
vector<Side> sideVec;
vector<int> winLoad;
vector<int> graph[maxn];
int n, m, d[maxn];
int visit[maxn];
void addSide(int a, int b, int val) {
sideVec.push_back(Side(a, b, val));
int dex = sideVec.size() - 1;
graph[a].push_back(dex);
}
void revBfs() {
queue<int> q;
memset(visit, 0, sizeof(visit));
q.push(n - 1); visit[n - 1] = 1;
d[n-1] = 0;
while(!q.empty()) {
int k = q.front(); q.pop();
for(int i = 0; i < graph[k].size(); i++) {
int dex = graph[k][i];
int u = sideVec[dex].v;
if(!visit[u]) {
visit[u] = 1;
d[u] = d[k] + 1;
q.push(u);
}
}
}
}
void bfs() {
memset(visit, 0, sizeof(visit));
visit[0] = 1;
winLoad.clear();
vector<int> next;
next.push_back(0);
for(int i = 0; i < d[0]; i++) {
int minVal = INF;
for(int j = 0; j < next.size(); j++) { //负责把最小的颜色编号存进winLoad中
int u = next[j];
for(int k = 0; k < graph[u].size(); k++) {
int dex = graph[u][k];
int v = sideVec[dex].v;
if(d[u] == d[v] + 1) minVal = min(minVal, sideVec[dex].val);
}
}
winLoad.push_back(minVal);
vector<int> next2;
for(int j = 0; j < next.size(); j++) {
int u = next[j];
for(int k = 0; k < graph[u].size(); k++) {
int dex = graph[u][k];
int v = sideVec[dex].v;
if(d[u] == d[v] + 1 && !visit[v] && sideVec[dex].val == minVal) {
visit[v] = 1;
next2.push_back(v);
}
}
}
next = next2;
}
printf("%d\n", winLoad.size());
printf("%d", winLoad[0]);
for(int i = 1; i < winLoad.size(); i++) printf(" %d", winLoad[i]);
printf("\n");
}
int main()
{
while(scanf("%d%d", &n, &m) == 2) {
//sideVec.size();
for(int i = 0; i < n; i++) graph[i].clear();
int a, b, val;
for(int i = 1; i <= m; i++) {
scanf("%d%d%d", &a, &b, &val);
addSide(a-1, b-1, val);
addSide(b-1, a-1, val);
}
revBfs(); //从终点开始bfs,求出每个点到终点的最小无权距离
bfs();
}
return 0;
}