裸的状压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 }
View Code

 

posted on 2015-04-22 21:49  Xs酱~  阅读(1096)  评论(3编辑  收藏  举报