首页 > 代码库 > BZOJ1097 旅游景点atr (最短路+状压DP)
BZOJ1097 旅游景点atr (最短路+状压DP)
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1097
分析:见注释。
1 #include <cstdio> 2 #include <vector> 3 #include <algorithm> 4 #include <cstring> 5 #include <functional> 6 #include <queue> 7 using namespace std; 8 9 #define Node pair<int, int>10 const int maxk = 20 + 2;11 const int INF = 1000000000;12 const int maxm = 200000 + 5;13 const int maxn = 20000 + 5;14 15 struct Edge {16 int to, w, nxt;17 Edge(int to = 0, int w = 0, int nxt = 0) : to(to), w(w), nxt(nxt) {};18 };19 20 int n, m, k, full_set;21 int tot, head[maxn], dis[maxk][maxk], f[1048576][maxk], depend[maxk], bin[maxk];22 int d[maxn];23 bool vis[maxn];24 Edge e[maxm << 1];25 26 int read() {27 int x = 0, f = 1; char ch = getchar();28 while (ch < ‘0‘ || ch > ‘9‘) { if (ch == ‘-‘) f = -1; ch = getchar(); };29 while (ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }30 return x * f;31 }32 33 void add_edge(int u, int v, int w) {34 e[++tot ].to = v, e[tot].w = w, e[tot].nxt = head[u], head[u] = tot;35 }36 37 // 求第(1 ~ k + 1)号节点到其余节点的单源最短路38 void dijkstra(int x) {39 priority_queue<Node, vector<Node>, greater<Node> > pq;40 for (int i = 1; i <= n; i++) d[i] = INF;41 for (int i = 1; i <= n; i++) vis[i] = 0;42 d[x] = 0;43 pq.push(make_pair(0, x));44 while (!pq.empty()) {45 int cur = pq.top().second; pq.pop();46 if (vis[cur]) continue; else vis[cur] = 1;47 for (int i = head[cur]; i; i = e[i].nxt) {48 if (d[cur] + e[i].w < d[e[i].to]) {49 d[e[i].to] = d[cur] + e[i].w;50 pq.push(make_pair(d[e[i].to], e[i].to));51 }52 }53 }54 for (int i = 1; i <= k + 1; i++) dis[x][i] = d[i];55 dis[x][k + 2] = d[n];56 }57 58 void dp() {59 for (int old_set = 0; old_set <= full_set; old_set++) // 枚举节点集合60 for (int cur = 1; cur <= k + 1; cur++) { // 枚举cur为源点61 if (f[old_set][cur] == -1) continue; // 不存在此状态的表示的路径则返回62 for (int nxt = 2; nxt <= k + 1; nxt++) { //枚举nxt为汇点63 int new_set = (old_set | bin[nxt - 2]); // 将nxt号节点纳入路径集合64 if ((old_set & depend[nxt]) == depend[nxt]) // 判断在nxt号节点停留前是否已经在题目要求的节点停留过65 if (f[old_set][cur] + dis[cur][nxt] < f[new_set][nxt] || f[new_set][nxt] == -1) // 更新最短路66 f[new_set][nxt] = f[old_set][cur] + dis[cur][nxt];67 }68 }69 }70 71 int main() {72 bin[0] = 1; for (int i = 1; i < 22; i++) bin[i] = bin[i - 1] << 1; // bin[i]表示(i - 2)号节点是否纳入路径73 n = read(); m = read(); k = read(); full_set = bin[k] - 1; // full_set表示2 ~ (k + 1)号节点的全集74 for (int i = 1, u, v, w; i <= m; i++) { // 建图75 u = read(); v = read(); w = read();76 add_edge(u, v, w);77 add_edge(v, u, w);78 }79 for (int i = 1; i <= k + 1; i++) dijkstra(i); // 求出1 ~ (k + 1)号节点到其余节点的单源最短路80 int x = read();81 for (int i = 1, u, v; i <= x; i++) {82 u = read(); v = read();83 depend[v] += bin[u - 2]; // 表示u号(用二进制的第u - 2位表示)节点在v号节点前停留84 }85 memset(f, -1, sizeof(f)); f[0][1] = 0; // 初始化,f[i][j]表示经过i集合(范围2 ~ k + 1)中所有节点*且当前停留在j号节点*的最短路86 dp(); // 求出走完前(1 ~ k + 1) 号节点最终停留在第i号节点的最短路87 int ans = INF;88 for (int i = 1; i <= k + 1; i++)89 if (f[full_set][i] != -1) ans = min(ans, f[full_set][i] + dis[i][k + 2]); // 找出走完(1 ~ k + 1)号节点停留在i到n的最短路90 printf("%d", ans); // 输出91 return 0;92 }
BZOJ1097 旅游景点atr (最短路+状压DP)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。