DFS与BFS以及图的存储以及遍历

目录

一,用dfs解决全排列

二,用dfs解决八皇后问题

三,用bfs解决迷宫问题

四,图的邻接表的存储

五,图的bfs

六,有向图的拓扑序列


一,用dfs解决全排列

//dfs 全排列
#include<iostream>
#include<algorithm>

using namespace std;

const int N = 1e5 + 10;

int a[N],v[N];
int n;

void dfs(int x)
{
	if (x == n)
	{
		for (int i = 0; i < n; i++)
			printf("%d ", a[i]);
		printf("\n");
		return;
	}
	for (int i = 1; i <=n ; i++)
	{
		if (!v[i])
		{
			a[x] = i;
			v[i] = 1;
			dfs(x + 1);
			v[i] = 0;
		}
	}
}
int main()
{
	
	scanf("%d", &n);
	dfs(0);
	return 0;
}

二,用dfs解决八皇后问题

//dfs 八皇后
#include<iostream>
#include<algorithm>

using namespace std;

const int N = 20;

int lie[N], duijiao[N], fanduijiao[N];
int n;
char a[N][N];


void dfs(int x)
{
	if (x == n)
	{
		for (int i = 0; i < n; i++)
			puts(a[i]);
		puts(" ");
		return;
	}
	for (int j = 0; j < n; j++)
	{
		if (!lie[j] && !duijiao[j+x] && !fanduijiao[j-x+n])
		{
			a[x][j] = 'Q';
			lie[j] = duijiao[j+x] = fanduijiao[j-x+n] = 1;
			dfs(x + 1);
			lie[j] = duijiao[j+x] = fanduijiao[j-x+n] = 0;
			a[x][j] = '*';
		}
	}
}
int main()
{
	scanf("%d", &n);

	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			a[i][j] = '*';
	dfs(0);
	return 0;
}

三,用bfs解决迷宫问题

//bfs解决迷宫问题
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

const int N = 110;

typedef struct stu
{
	int x;
	int y;
	int step;
};
char a[N][N];
int sx, sy, fx, fy;

int dx[4] = { 0,1,0,-1 };
int dy[4] = { 1,0,-1,0 };

int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		int n, m;
		scanf("%d%d", &n, &m);
		getchar();
		queue<stu>q;
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < m; j++)
			{
				scanf("%c", &a[i][j]);
				if (a[i][j] == 'S')
				{
					sx = i;
					sy = j;
				}
				if (a[i][j] == 'E')
				{
					fx = i;
					fy = j;
				}
			}
			getchar();
		}
		q.push({ sx,sy,0 });
		a[sx][sy] = '#';
		int flag = 0;
		while (!q.empty())
		{
			auto p = q.front();
			if (p.x == fx && p.y == fy)
			{
				printf("%d\n", p.step);
				flag = 1;
				break;
			}
			q.pop();
			for (int i = 0; i < 4; i++)
			{
				int tx = p.x + dx[i];
				int ty = p.y + dy[i];
				if (tx >= 0 && tx < n && ty >= 0 && ty < m && (a[tx][ty] == '-')||(a[tx][ty] == 'E'))
				{
					q.push({ tx,ty,p.step + 1 });
					a[tx][ty] = '#';
				}
			}
		}
		if (flag == 0)
			printf("-1\n");
	}
	return 0;
}

四,图的邻接表的存储

//建立一条从a指向b的边
//链表头插法,头结点要初始化指向-1
void add(int a, int b)
{
	e[idx] = b;
	ne[idx] = h[a];
	h[a] = idx++;
}

五,图的bfs

//在一个图中,给出m条有向边,求点1到点n的最短距离,若点1到达不了点n则输出-1
#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 100010;

int n, m;
int h[N], e[N], ne[N], idx;
//d表示距离   q模拟队列
int q[N],d[N];
 
//建立一条从a指向b的边
//链表头插法,头结点要初始化指向-1
void add(int a, int b)
{
	e[idx] = b;
	ne[idx] = h[a];
	h[a] = idx++;
}

int bfs()
{
	q[0] = 1;
	int hh = 0, tt = 0;
	memset(d, -1, sizeof d);
	d[1] = 0;
	while (hh <= tt)
	{
		int t = q[hh++];
		for (int i = h[t]; i != -1; i = ne[i])
		{
			int j = e[i];
			if (d[j] == -1)
			{
				q[++tt] = j;
				d[j] = d[t] + 1;
			}
		}
	}
	return d[n];
}
int main()
{
	cin >> n >> m;
	memset(h, -1, sizeof h);
	for (int i = 0; i < m; i++)
	{
		int a, b;
		cin >> a >> b;
		add(a, b);
	}
	cout << bfs() << endl;
	return 0;
}

六,有向图的拓扑序列

//拓扑排序就是每次找到入度为0的点,将其入队,最后输出拓扑序列
#include<iostream>               //拓扑排序,洛谷B3644
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 100010;

int n, m;
int h[N], e[N], ne[N], idx;
//d表示点的度数,q表示队列
int d[N], q[N];

void add(int a, int b)
{
	e[idx] = b;
	ne[idx] = h[a];
	h[a] = idx++;
}

bool topsort()
{
	int hh = 0, tt = -1;
	for (int i = 1; i <= n; i++)
	{
		if (d[i] == 0)
			q[++tt] = i;
	}
	while (hh <= tt)
	{
		int t = q[hh++];
		for (int i = h[t]; i != -1; i = ne[i])
		{
			int j = e[i];
			d[j]--;
			if (d[j] == 0)
				q[++tt] = j;
		}
	}
	if (tt == n - 1)
		return true;
	else
		false;
}
int main()
{
	cin >> n;
	memset(h, -1, sizeof h);
	for (int i = 1; i <= n; i++)
	{
		int j;
		while (1)
		{
			cin >> j;
			if (j == 0)
				break;
			else
			{
				add(i, j);
				d[j]++;
			}
		}
	}
	if (topsort())
	{
		for (int i = 0; i < n; i++)
			cout << q[i] << " ";
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值