【题意】:每个节点可以最多访问两次,求访问完所有点的最小费用。
【题解】:求哈密顿路,只是多了点条件,果断状态压缩dp+三进制。
通过这题瞬间领会了k进制的操作,好!
【代码】:
1 #include "iostream"
2 #include "cstdio"
3 #include "cstring"
4 #include "algorithm"
5 #include "vector"
6 #include "queue"
7 #include "cmath"
8 #include "string"
9 #include "cctype"
10 #include "map"
11 #include "iomanip"
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define fi first
16 #define se second
17 #define lc(x) (x << 1)
18 #define rc(x) (x << 1 | 1)
19 #define lowbit(x) (x & (-x))
20 #define ll long long
21 const int inf = 1 << 20;
22 int dp[11][65000];
23 int maz[15][15];
24 int p[15];
25
26 void init() {
27 p[0] = 1;
28 for(int i = 1; i < 15; i++) p[i] = p[i-1] * 3;
29 }
30
31 int n, m;
32 int main() {
33 int a, b, c;
34 init();
35 while(~scanf("%d%d", &n, &m)) {
36 for(int i = 0; i < n; i++)
37 for(int j = 0; j < n; j++)
38 maz[i][j] = inf;
39 while(m--) {
40 cin >> a >> b >> c;
41 a--, b--;
42 if(c < maz[a][b]) maz[a][b] = maz[b][a] = c;
43 }
44
45 int nn = p[n];
46 for(int i = 0; i < n; i++) {
47 for(int j = 0; j < nn; j++) dp[i][j] = inf;
48 dp[i][p[i]] = 0;
49 }
50
51 for(int j = 0; j < nn; j++) {
52 for(int i = 0; i < n; i++) {
53 int x = j / p[i] % 3;
54 if(x > 0) {
55 for(int k = 0; k < n; k++) {
56 int y = j / p[k] % 3;
57 if(maz[i][k] != inf && y <= 1) {
58 int nmask = j + p[k];
59 dp[k][nmask] = min(dp[k][nmask], dp[i][j] + maz[i][k]);
60 }
61 }
62 }
63 }
64 }
65 int ans = inf;
66 for(int i = 0; i < n; i++) {
67 for(int j = 0; j < nn; j++) {
68 bool flag = true;
69 for(int k = 0; k < n; k++)
70 if((j / p[k] % 3) == 0) {
71 flag = false;
72 break;
73 }
74 if(flag) ans = min(ans, dp[i][j]);
75 }
76 }
77
78 if(ans != inf) cout << ans << endl;
79 else cout << -1 << endl;
80 }
81 return 0;
82 }
83