题解 P3959 宝藏
Minakami_Yuki · · 题解
重边卡了
题目链接
P3959 宝藏
题意简述
求给定图的最小代价生成树。
其中代价定义为:
其中
解题思想
首先
然后可以基于搜索,枚举一下每次加的边的起点,更新新点的深度,记得要回溯。
最小化就是状压
还有一个坑点就是,读入是要判重边的,不加会少
参考代码
#include <cstdio>
#include <cstring>
#include <cctype>
const int N = 15;
inline int read() {
char ch = getchar(); int r = 0, w = 1;
while(!isdigit(ch)) {if(ch == '-') w = -1; ch = getchar();}
while(isdigit(ch)) {r = r * 10 + ch - '0', ch = getchar();}
return r * w;
}
inline int min(int a, int b) {return a < b ? a : b;}
int n, m, ans = 0x7fffffff;
int dp[1 << N], dis[N][N], d[N];
bool cnt[N][N];
inline void add(int x, int y, int z) {
dis[x][y] = dis[y][x] = z;
cnt[x][y] = cnt[y][x] = 1;
}
void dfs(int s) {
for(register int x = 1; x <= n; x++) {
if((1 << (x - 1)) & s) {
for(register int y = 1; y <= n; y++) {
if(cnt[x][y] && !((1 << (y - 1)) & s)) {
if(dp[s | (1 << (y - 1))] > dp[s] + dis[x][y] * d[x]) {
int tmp = d[y];
d[y] = d[x] + 1;
dp[s | (1 << (y - 1))] = dp[s] + dis[x][y] * d[x];
dfs(s | (1 << (y - 1)));
d[y] = tmp;
}
}
}
}
}
}
int main() {
n = read(), m = read();
memset(dis, 0x3f, sizeof dis);
for(register int i = 1; i <= m; i++) {
int x = read(), y = read(), z = read();
if(z < dis[x][y]) add(x, y, z);
}
for(register int rt = 1; rt <= n; rt++) {
memset(d, 0x3f, sizeof d);
for(register int i = 1; i <= (1 << n) - 1; i++) dp[i] = 0x7fffffff;
dp[1 << (rt - 1)] = 0;
d[rt] = 1;
dfs(1 << (rt - 1));
ans = min(ans, dp[(1 << n) - 1]);
}
printf("%d\n", ans);
return 0;
}