Files
python/TangDou/AcWing/StateCompression/529_dfs_1.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

72 lines
2.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x01010101; // 这个上限有点意思,需要仔细思考
const int N = 15; // 点的个数上限 
int g[N][N]; // 记录边,就是地图
int n, m; // n个节点,m条边
vector<int> p[N]; // 第一维:哪一行;第二维:此行第几个是哪个点
bool st[N]; // 每个点是否被用过
int res = INF; // 结果
/*
* u:第u层
* k:正在枚举第几号节点,尝试将这个节点填充到u层中去
* cnt:已经使用了cnt个点
* sum:目前生成树最小价值
*/
void dfs(int u, int k, int cnt, int sum) {
if (sum >= res) return; // 走一半就比最优值大,剪枝
if (p[u - 1].size() == 0) return; // 上一层没有选入点(上层为空),树无法继续构建,递归出口
if (cnt == n) { // 所有点都已经被构建到树中,结果有资格参选最优解
res = sum; // 因为上面有最优剪枝,大的都被提前返回了,到达这里时肯定是更小的值
return;
}
if (k > n) { // 该层所有点都讨论过一遍,继续下一层,回到1号节点处开始
dfs(u + 1, 1, cnt, sum);
return;
}
// 如果u层,k号点被标识为用过了
if (st[k]) { // 该点已用,继续讨论下一个节点
dfs(u, k + 1, cnt, sum);
return;
}
int cost = INF; // 找到该点与上层的最小联系
for (int i = 0; i < p[u - 1].size(); i++) // 若没有联系(即与上层所有点不连通),则mini是INF,会被最优性剪枝减去
cost = min(cost, g[p[u - 1][i]][k]); // 上一行的每个节点,如果与k号节点的边相连,并且,权值最小的话,更新cost
// 找到了上一层到u层,使得k点点亮的最小代价值
// 选用此点(可能1)
st[k] = 1; // 标识k点已使用
p[u].push_back(k);
dfs(u, k + 1, cnt + 1, sum + cost * u);
p[u].pop_back();
st[k] = 0; // 回溯
// 不用此点(可能2)
dfs(u, k + 1, cnt, sum);
}
int main() {
memset(g, 0x3f, sizeof g); // 数组初始化
scanf("%d %d", &n, &m);
while (m--) {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
g[a][b] = g[b][a] = min(g[a][b], c); // 无向图
}
for (int i = 1; i <= n; i++) { // 每个点都当一次根
st[i] = 1; // i点已用
p[0].push_back(i); // 根是第0层,第1个放的是i
dfs(1, 1, 1, 0); // 从第一层,第一个节点,已经使用了一个节点(根),现在的代价是0
p[0].pop_back(); // 回溯
st[i] = 0; // 回溯
}
cout << res << endl;
return 0;
}