BZOJ1097 [POI2007]旅游景点atr

首先预处理出来前K个点互相之间的最短路,直接Dijkstra就好了

然后就变成了状压DP。。。随便写一下好了

  1 /**************************************************************
  2     Problem: 1097
  3     User: rausen
  4     Language: C++
  5     Result: Accepted
  6     Time:18456 ms
  7     Memory:98872 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <cstring>
 12 #include <algorithm>
 13 #include <queue>
 14  
 15 using namespace std;
 16 const int N = 2e4 + 5;
 17 const int M = 2e5 + 5;
 18 const int K = 22;
 19 const int Tot_S = 1 << 20;
 20 const int inf = 1e9;
 21  
 22 struct edge {
 23     int next, to, v;
 24     edge(int _n = 0, int _t = 0, int _v = 0) : next(_n), to(_t), v(_v) {}
 25 } e[M << 1];
 26  
 27 struct heap_node {
 28     int v, to;
 29     heap_node(int _v = 0, int _t = 0) : v(_v), to(_t) {}
 30      
 31     inline bool operator < (const heap_node &p) const {
 32         return v > p.v;
 33     }
 34 };
 35  
 36 int n, m, k, ans;
 37 int first[N], tot;
 38 int bin[K], a[K];
 39 int dis[K][K], d[N];
 40 int S, S1;
 41 int f[Tot_S][K];
 42 priority_queue <heap_node> h;
 43  
 44 inline int read() {
 45     static int x;
 46     static char ch;
 47     x = 0, ch = getchar();
 48     while (ch < '0' || '9' < ch)
 49         ch = getchar();
 50     while ('0' <= ch && ch <= '9') {
 51         x = x * 10 + ch - '0';
 52         ch = getchar();
 53     }
 54     return x;
 55 }
 56  
 57 inline void Add_Edges(int x, int y, int z) {
 58     e[++tot] = edge(first[x], y, z), first[x] = tot;
 59     e[++tot] = edge(first[y], x, z), first[y] = tot;
 60 }
 61  
 62 inline void add_to_heap(int p) {
 63     static int x;
 64     for (x = first[p]; x; x = e[x].next)
 65         if (d[e[x].to] == -1)
 66             h.push(heap_node(e[x].v + d[p], e[x].to));
 67 }
 68  
 69 void Dijkstra(int S) {
 70     static int p;
 71     memset(d, -1, sizeof(d));
 72     while (!h.empty()) h.pop();
 73     d[S] = 0, add_to_heap(S);
 74     while (!h.empty()) {
 75         if (d[h.top().to] != -1) {
 76             h.pop();
 77             continue;
 78         }
 79         p = h.top().to;
 80         d[p] = h.top().v;
 81         h.pop();
 82         add_to_heap(p);
 83     }
 84 }
 85  
 86 int main() {
 87     int i, j, x, y, z;
 88     n = read(), m = read(), k = read();
 89     for (i = 1; i <= m; ++i) {   
 90         x = read(), y = read(), z = read();
 91         Add_Edges(x, y, z);
 92     }
 93     for (i = 1; i <= k + 1; ++i) {
 94         Dijkstra(i);
 95         for (dis[i][0] = d[n], j = 1; j <= k + 1; ++j)
 96             dis[i][j] = d[j];
 97     }
 98     for (i = bin[0] = 1; i <= k + 1; ++i) bin[i] = bin[i - 1] << 1;
 99     for (x = read(), i = 1; i <= x; ++i)
100         y = read(), z = read(), a[z] += bin[y - 2];
101      
102     memset(f, 0x3f, sizeof(f));
103     for (S = f[0][1] = 0; S < bin[k]; ++S)
104         for (i = 1; i <= k + 1; ++i) if (f[S][i] != 0x3f3f3f3f)
105             for (j = 2; j <= k + 1; ++j) {
106                 S1 = S | bin[j - 2];
107                 if ((S & a[j]) == a[j]) f[S1][j] = min(f[S1][j], f[S][i] + dis[i][j]);
108             }
109     for (ans = inf, i = 1; i <= k + 1; ++i)
110         ans = min(ans, f[bin[k] - 1][i] + dis[i][0]);
111     printf("%d
", ans);
112     return 0;
113 }
View Code
By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
原文地址:https://www.cnblogs.com/rausen/p/4426387.html