心得:
dfs 转 bfs 的要点:
- 在dfs中控制回溯的分支的循环中,将向下层递归的语句改为压入队列(一般借助结构体保存各种环境信息)。
- bfs使用优先队列可以剪掉大部分的无用分支。
//图的结点没有出边则表示没回路
//优先队列可以剪掉大部分的无用分支
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
#define N 10
struct Node{
int v;
int len;
int x[N];
int rl;
int sl;
Node(int v_ = 0,int len_ = 0,int rl_ = 0):v(v_),len(len_),rl(rl_){}
bool operator <(const Node& t1) const{
return this ->sl > t1.sl; //< 大值优先, '>'小值优先
}
};
int n,e;
int m[N][N];
int bestx[N];
int bestl;
int minlen[N];
int mintotal;
void bfs(int setup){
priority_queue<Node> q;
Node newnode,t;
for(int i = 1; i <= n; i++){
newnode.x[i] = i;
}
newnode.v = 2;
newnode.len = 0;
newnode.rl = mintotal;
newnode.sl = mintotal;
q.push(newnode);
while(!q.empty()){
t = q.top();
q.pop();
int floor = t.v;
if(t.v == n + 1){
if(m[t.x[floor - 1]][setup] != INT_MAX){
bestl = t.len + m[t.x[floor - 1]][setup];
for(int i = 1; i <= n; i++){
bestx[i] = t.x[i];
}
bestx[n + 1] = setup;
return ;
}
}
for(int i = floor; i<= n; i++){
if(m[t.x[floor - 1]][t.x[i]] != INT_MAX && t.sl < bestl){
newnode.v = floor + 1;
newnode.len = t.len + m[t.x[floor - 1]][t.x[i]];
newnode.rl -= minlen[t.x[i]];
newnode.sl = newnode.rl + newnode.len;
for(int j = 1; j <= n; j++){
newnode.x[j] = t.x[j];
}
swap(newnode.x[i],newnode.x[floor]);
q.push(newnode);
}
}
}
}
int main(){
cin >> n >> e;
for(int i = 0; i <= n; i++){
minlen[i] = INT_MAX;
for(int j = 0; j <= n; j++){
m[i][j] = INT_MAX;
}
}
for(int i = 0; i < e; i++){
int v,u,len;
cin >> v >> u >> len;
m[v][u] = len;
m[u][v] = len;
minlen[v] = min(minlen[v], m[v][u]);
minlen[u] = min(minlen[u], m[u][v]);
}
for(int i = 1; i <= n; i++){
mintotal += minlen[i];
}
bestl = INT_MAX;
bfs(1);
for(int i = 1; i <= n + 1; i++){
cout << bestx[i] << " ";
}
cout << endl;
cout << bestl << endl;
}
/*
4 6
1 2 15
1 3 30
1 4 5
2 3 6
2 4 12
3 4 3
*/