# 洛谷P3959 宝藏

#### 最优化剪枝

#include <bits/stdc++.h>
#define inf 1061109567
using namespace std;
int n, m, mp, ans, now, totn, dis[101][101], to[101][101], vis[101], cnt[101], used[101], mindis[101];//used表示当前选择的点的编号
int minn = 2147483647;
bool cmp(int a, int b) {return dis[mp][a] < dis[mp][b];}
void dfs(int pos1, int pos2)
{
if (totn == n)
{
minn = min(ans, minn);
return;
}
for (int k = pos1; k <= totn; k++)//直接搜索当前还没有搜索完边的点，搜索要减少重复计算，我们之前的点肯定都已经搜索过了，因此不许要在继续搜索了。
{
int i = used[k];
if (ans + now * vis[i] >= minn) return;//当前的最优长度乘上当前的最优深度即为最优解
for (int j = pos2; j <= cnt[i]; j++)
{
int t = to[i][j];
if (vis[t]) continue;
used[++totn] = t;
vis[t] = vis[i] + 1;
ans += dis[i][t] * vis[i];
now -= mindis[t];
dfs(k, j + 1);
ans -= dis[i][t] * vis[i];
now += mindis[t];
vis[t] = 0;
--totn;
}
pos2 = 1;
}
}
inline void init()
{
memset(dis, 0x3f, sizeof(dis));
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
if (dis[a][b] == inf)
++cnt[a], to[a][cnt[a]] = b, ++cnt[b], to[b][cnt[b]] = a;
dis[a][b] = dis[b][a] = min(dis[a][b], c);
}
for (int i = 1; i <= n; i++)
mp = i, sort(to[i] + 1, to[i] + cnt[i] + 1, cmp);
for (int i = 1; i <= n; i++)
mindis[i] = dis[i][to[i][1]], now += mindis[i];
}
int main()
{
init();
for (int i = 1; i <= n; i++)
{
ans = 0;
used[totn = 1] = i;
vis[i] = 1;
now -= dis[i][to[i][1]];
dfs(1, 1);
now += dis[i][to[i][1]];
vis[i] = 0;
}
printf("%d", minn);
return 0;
}

posted @ 2019-11-11 18:14  刘文尧  阅读(94)  评论(0编辑  收藏