# BZOJ4006 [JLOI2015]管道连接

$$f_S=\min\{f_S,f_s+f_{S-s}|s\subset S\}$$

  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
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() {
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;
86     for (i = 1; i <= m; ++i) {
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
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酱~  阅读(878)  评论(3编辑  收藏