DS-实验12

小细节:
参考资料
课本p397.
【1】上三角矩阵所需空间(n^2-n)/2字节(?)
【2】确定邻接至或者邻接于一个给定节点的集合需要用时B(n),增加或者删除只需要B(1)
p398
【3】邻接链表不在意顺序吗(?)
【4】一个指针、int都需要4字节存储空间

学到了:
【1】如果比较好多路径取得最短长度,没必要存储好多路径,直接算完就比较,大的就不用存进去了,保持更新最小值就可以;即便是没有走完,当前走过路径大于之前最短路径,也没必要再走下去
【2】
参考图论(一):DFS,BFS,邻接链表,并查集
DFS:(一条路末端再回溯一个节点继续走到末端)
【沿着图的某一条分支遍历直到末端,然后回溯,再沿着另一条进行同样的遍历。】
tip:
【1】void *memset(void *s, int ch, size_t n); *
函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。
【2】
setw(int n) *是c++中在输出操作中使用的字段宽度设置,设置输出的域宽,n表示字段宽度。只对紧接着的输出有效,紧接着的输出结束后又变回默认的域宽。
当后面紧跟着的输出字段长度小于n的时候,在该字段前面用空格补齐;当输出字段长度大于n时,全部整体输出。

/***先输入n个结点,m条边,之后输入无向图的m条边,之后对上图输出DFS遍历的结点顺序***/
//这个程序是给边输出点
#include <iostream>
#include <iomanip>//没见过
#define nmax 110
#define inf 999999999
using namespace std;
int n, m, cnt;//结点数,边数,计数值
int edge[nmax][nmax];//邻接矩阵
int mark[nmax];//结点访问标记
void dfs(int cur){
//找找有没有下一个点然后输出
	cnt++;
	/***operation***/
	if(cnt == 1)
		cout << cur;
	else 
		cout<<" "<<cur;
		//cout << setw(3) << cur;setw(3)也就是把输出的数字设置为三位的长度,因为是个位数,效果是空两格
	/***operation***/
	if(cnt == n) return;//不必往下了
	else{//往下遍历了
		int i;
		for(i = 1; i <= n; i++){
			if(edge[cur][i] == 1 && mark[i] == 0){
			//当前节点存在边cur-i,如果i还没有被走过,那就去;走过了就换一条。
				mark[i] = 1;//现在走到了这个点
				dfs(i);//找这个点有没有下一个点
			}
		}
		return;
	}
 
}
 
int main(){
	while(cin >> n >> m && n != 0){
		//初始化邻接矩阵
		int i, j;
		for(i = 1; i <= n; i++){
			for(j = 1; j <= n; j++){
				edge[i][j] = inf;
			}
			edge[i][i] = 0;
		}
		int a, b;
		while(m--){
			cin >> a >> b;
			edge[a][b] = edge[b][a] = 1;
		}
		//以dnf(1)为起点开始递归遍历
		memset(mark, 0, sizeof(mark));
		//将mark中当前位置后面的 sizeof(mark)个字节 用 0 替换。
		//mark是结点访问标记
		cnt = 0;
		mark[1] = 1;//0是未经历,1是已经走过
		//考虑的好周到啊...把点1被走过完美考虑边缘数据
		//是一条路内部吗还是啥,我不知道怎么在切换到下一条路修改标记
		//噢不需要输出很多路,只需要一种方式走出来一条就可以了
		dfs(1);//1代表从1开始吗
		cout << endl;
	}
	return 0;
}
/***先输入n个结点,m条边,之后输入有向图的m条边,边的前两元素表示起始结点,第三个值表权值,输出1号城市到n号城市的最短距离***/
/***算法的思路是访问所有的深度遍历路径,需要在深度遍历返回时将访问标志置0***/
#include <iostream>
#include <iomanip>
#define nmax 110
#define inf 999999999
using namespace std;
int n, m, minPath, edge[nmax][nmax], mark[nmax];//结点数,边数,最小路径,邻接矩阵,结点访问标记
void dfs(int cur, int dst){
	//下面这一句惊为天人!好耶!!!!!!!!
	if(minPath < dst) return;//当前走过路径大于之前最短路径,没必要再走下去
	if(cur == n){//临界条件,也就是成功到达了
	//直接在这里比较了不错
		if(minPath > dst) minPath = dst;
		return;
	}
	else{
		int i;
		for(i = 1; i <= n; i++){
			if(edge[cur][i] != inf && edge[cur][i] != 0 && mark[i] == 0){
				mark[i] = 1;
				dfs(i, dst+edge[cur][i]);//直接在此处!妙啊!
				mark[i] = 0;			
			}
		}
		return;
	}
}
 
int main(){
	while(cin >> n >> m && n != 0){
		//初始化邻接矩阵
		int i, j;
		for(i = 1; i <= n; i++){
			for(j = 1; j <= n; j++){
				edge[i][j] = inf;
			}
			edge[i][i] = 0;
		}
		int a, b;
		while(m--){
			cin >> a >> b;
			cin >> edge[a][b];
		}
		//以dnf(1)为起点开始递归遍历
		memset(mark, 0, sizeof(mark));
		minPath = inf;
		mark[1] = 1;
		dfs(1, 0);
		cout << minPath << endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值