标签:起点 旅游 ons 正是 set str 并且 立交桥 最短路
[BZOJ1097][POI2007]旅游景点atr
试题描述
输入
输出
输入示例
8 15 4 1 2 3 1 3 4 1 4 4 1 6 2 1 7 3 2 3 6 2 4 2 2 5 2 3 4 3 3 6 3 3 8 6 4 5 2 4 8 6 5 7 4 5 8 6 3 2 3 3 4 3 5
输出示例
19
数据规模及约定
见“输入”
题解
虽然点数很多,但是我们只需要关心 K+2 个点(K 个必须停留的节点以及起点和终点)之间的最短路就好了,于是可以做最多 22 次最短路预处理处 Dis[i][j] 表示第 i 个关键点到第 j 个关键点的距离。
接下来就是 dp,f(S, i) 表示已经在集合 S 中的点停留过了,现在在节点 i 所需要的最短距离。你可以记录一个 bef[i] 表示在 i 停留之前需要停留的节点集合,然后转移的时候看看 bef[i] 是不是当前状态 S 的子集,这就是细节了。
注意特判 K = 0 的情况!!!
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <queue>
using namespace std;
int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); }
return x * f;
}
#define maxn 20010
#define maxm 400010
#define maxk 25
#define maxs 1048576
#define oo (1ll << 60)
#define LL long long
int n, m, K, head[maxn], to[maxm], nxt[maxm], dist[maxm], idk[maxk];
LL Dis[maxk][maxk];
void AddEdge(int a, int b, int c) {
to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m;
swap(a, b);
to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m;
return ;
}
LL d[maxn];
bool vis[maxn];
struct Node {
int u, d;
Node() {}
Node(int _, int __): u(_), d(__) {}
bool operator < (const Node& t) const { return d > t.d; }
};
priority_queue <Node> Q;
void ShortPath(int si) {
int s = idk[si];
for(int i = 1; i <= n; i++) d[i] = oo;
memset(vis, 0, sizeof(vis));
d[s] = 0; Q.push(Node(s, 0));
while(!Q.empty()) {
int u = Q.top().u; Q.pop();
if(vis[u]) continue;
vis[u] = 1;
for(int e = head[u]; e; e = nxt[e]) if(d[to[e]] > d[u] + dist[e]) {
d[to[e]] = d[u] + dist[e];
if(!vis[to[e]]) Q.push(Node(to[e], d[to[e]]));
}
}
for(int i = 1; i <= K + 2; i++) if(i != si) Dis[si][i] = d[idk[i]];
return ;
}
int bef[maxk];
LL f[maxs][maxk];
void up(LL& a, LL b) {
a = min(a, b);
return ;
}
int main() {
n = read(); int m = read(); K = read();
for(int i = 1; i <= m; i++) {
int a = read(), b = read(), c = read();
AddEdge(a, b, c);
}
for(int i = 2; i <= K + 1; i++) idk[i-1] = i;
idk[K+1] = 1; idk[K+2] = n;
m = read();
for(int i = 1; i <= m; i++) {
int a = read() - 1, b = read() - 1;
bef[b] |= (1 << a - 1);
}
for(int i = 1; i <= K + 2; i++) ShortPath(i);
int all = (1 << K) - 1;
for(int S = 0; S <= all; S++)
for(int i = 1; i <= K; i++) f[S][i] = oo;
for(int i = 1; i <= K; i++) if(!bef[i]) f[1<<i-1][i] = Dis[K+1][i];
for(int S = 0; S <= all; S++)
for(int i = 1; i <= K; i++) if(f[S][i] < oo)
for(int j = 1; j <= K; j++) if((S >> j - 1 & 1) == 0 && (S & bef[j]) == bef[j])
up(f[S|(1<<j-1)][j], f[S][i] + Dis[i][j]);
LL ans = oo;
for(int i = 1; i <= K; i++) if(f[all][i] < oo) up(ans, f[all][i] + Dis[i][K+2]);
printf("%lld\n", K ? ans : Dis[1][2]);
return 0;
}
标签:起点 旅游 ons 正是 set str 并且 立交桥 最短路
原文地址:http://www.cnblogs.com/xiao-ju-ruo-xjr/p/6726013.html