裸的状压DP
令$f_S$表示包含颜色集合S的最小斯坦纳生成森林的值,于是有:
$$f_S=\min\{f_S,f_s+f_{S-s}|s\subset S\}$$
然后嘛。。。还是裸的斯坦纳树搞搞。。。又是个状压【摔!
貌似会TLE的说【额。。。
然后PoPoQQQ大爷分析了一番,说,大概1E的复杂度,不会T!
好,那就不会好了!(也太不求上进了吧)
1 /************************************************************** 2 Problem: 4006 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:7272 ms 7 Memory:5160 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #include <algorithm> 13 14 using namespace std; 15 const int M = 3e3 + 5; 16 const int N = 1e3 + 5; 17 const int K = 25; 18 const int Sz_q = N * 64; 19 const int inf = 0x3f3f3f3f; 20 21 inline int read(); 22 23 struct edge { 24 int next, to, v; 25 edge(int _n = 0, int _t = 0, int _v = 0) : next(_n), to(_t), v(_v) {} 26 } e[M << 1]; 27 28 struct point { 29 int c, w; 30 31 inline void get() { 32 c = read(), w = read(); 33 } 34 35 inline bool operator < (const point &p) const { 36 return c < p.c; 37 } 38 } p[K]; 39 40 int n, m, k, c, cnt; 41 int first[N], tot; 42 int f[1024][N], g[32]; 43 int l, r, q[Sz_q], v[N]; 44 45 inline void Add_Edges(int x, int y, int z) { 46 e[++tot] = edge(first[x], y, z), first[x] = tot; 47 e[++tot] = edge(first[y], x, z), first[y] = tot; 48 } 49 50 #define y e[x].to 51 void spfa(int *dis) { 52 static int x, p; 53 while (l != (r + 1) % Sz_q) { 54 p = q[l], v[p] = 0, ++l %= Sz_q; 55 for (x = first[p]; x; x = e[x].next) 56 if (dis[p] + e[x].v < dis[y]) { 57 dis[y] = dis[p] + e[x].v; 58 if (!v[y]) { 59 v[y] = 1; 60 if (dis[y] < dis[q[l]]) q[(l += Sz_q - 1) %= Sz_q] = y; 61 else q[++r %= Sz_q] = y; 62 } 63 } 64 } 65 } 66 #undef y 67 68 int work() { 69 static int S, s, i, res; 70 for (S = 1; S < 1 << cnt; ++S) { 71 for (i = 1; i <= n; ++i) { 72 for (s = S & (S - 1); s; (--s) &= S) 73 f[S][i] = min(f[S][i], f[s][i] + f[S ^ s][i]); 74 if (f[S][i] != inf) q[++r %= Sz_q] = i; 75 } 76 spfa(f[S]); 77 } 78 for (res = inf, i = 1; i <= n; ++i) 79 res = min(res, f[(1 << cnt) - 1][i]); 80 return res; 81 } 82 83 int main() { 84 int i, x, y, z, S, s, nowc; 85 n = read(), m = read(), k = read(); 86 for (i = 1; i <= m; ++i) { 87 x = read(), y = read(), z = read(); 88 Add_Edges(x, y, z); 89 } 90 for (i = 1; i <= k; ++i) p[i].get(); 91 sort(p + 1, p + k + 1); 92 for (nowc = -1, c = 0, i = 1; i <= k; ++i) { 93 if (p[i].c != nowc) nowc = p[i].c, ++c; 94 p[i].c = c; 95 } 96 97 memset(g, 0x3f, sizeof(g)); 98 for (S = 1; S < 1 << c; ++S) { 99 for (cnt = 0, i = 1; i <= k; ++i) 100 if (S & (1 << p[i].c - 1)) ++cnt; 101 memset(f, 0x3f, sizeof(f[0][0]) * N * (1 << cnt)); 102 for (cnt = 0, i = 1; i <= k; ++i) 103 if (S & (1 << p[i].c - 1)) f[1 << cnt++][p[i].w] = 0; 104 g[S] = work(); 105 } 106 for (S = 1; S < 1 << c; ++S) 107 for (s = S & (S - 1); s; (--s) &= S) 108 g[S] = min(g[S], g[s] + g[S ^ s]); 109 printf("%d\n", g[(1 << c) - 1]); 110 return 0; 111 } 112 113 inline int read() { 114 static int x; 115 static char ch; 116 x = 0, ch = getchar(); 117 while (ch < '0' || '9' < ch) 118 ch = getchar(); 119 while ('0' <= ch && ch <= '9') { 120 x = x * 10 + ch - '0'; 121 ch = getchar(); 122 } 123 return x; 124 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen