题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5418
题意:从1出发 每个点至少经过一次 最后回到1点的最短路径
首先用floyd处理点之间的最短距离 再状压求解
代码:
#include <stdio.h>
#include <ctime>
#include <math.h>
#include <limits.h>
#include <complex>
#include <string>
#include <functional>
#include <iterator>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <list>
#include <bitset>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <iostream>
#include <ctime>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int n, m, k, v;
int g[20][20];
int dp[(1<<16) + 10][20];
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
scanf("%d%d", &n, &m);
for (int i = 0;i <= n;i++)
for (int j = 0;j <= n;j++)
{
if (i == j) g[i][i] = 0;
else g[i][j] = inf;
}
int a, b, c;
while (m--)
{
scanf("%d%d%d", &a, &b, &c);
--a; --b;
g[a][b] = min(g[a][b], c);
g[b][a] = min(g[b][a], c);
}
for (int k = 0;k < n;k++)
for (int i = 0;i < n;i++)
for (int j = 0;j < n;j++)
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
memset(dp,inf,sizeof(dp));
dp[0][0] = 0;
for (int i = 0;i <= (1 << n) - 1;i++)
for (int v = 0;v < n;v++)
if (dp[i][v] != inf)
{
for (int u = 0;u < n;u++)
dp[i | (1 << u)][u] = min(dp[i | (1 << u)][u], dp[i][v] + g[v][u]);
}
printf("%d\n", dp[(1 << n) - 1][0]);
}
return 0;
}