小细节:
参考资料
课本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;
}