[BZOJ1097][POI2007]旅游景点atr
生活随笔
收集整理的這篇文章主要介紹了
[BZOJ1097][POI2007]旅游景点atr
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
[BZOJ1097][POI2007]旅游景點atr
試題描述
FGD想從成都去上海旅游。在旅途中他希望經過一些城市并在那里欣賞風景,品嘗風味小吃或者做其他的有趣的事情。經過這些城市的順序不是完全隨意的,比如說FGD不希望在剛吃過一頓大餐之后立刻去下一個城市登山,而是希望去另外什么地方喝下午茶。幸運的是,FGD的旅程不是既定的,他可以在某些旅行方案之間進行選擇。由于FGD非常討厭乘車的顛簸,他希望在滿足他的要求的情況下,旅行的距離盡量短,這樣他就有足夠的精力來欣賞風景或者是泡MM了^_^.整個城市交通網絡包含N個城市以及城市與城市之間的雙向道路M條。城市自1至N依次編號,道路亦然。沒有從某個城市直接到它自己的道路,兩個城市之間最多只有一條道路直接相連,但可以有多條連接兩個城市的路徑。任意兩條道路如果相遇,則相遇點也必然是這N個城市之一,在中途,由于修建了立交橋和下穿隧道,道路是不會相交的。每條道路都有一個固定長度。在中途,FGD想要經過K(K<=N-2)個城市。成都編號為1,上海編號為N,而FGD想要經過的N個城市編號依次為2,3,…,K+1.舉例來說,假設交通網絡如下圖。FGD想要經過城市2,3,4,5,并且在2停留的時候在3之前,而在4,5停留的時候在3之后。那么最短的旅行方案是1-2-4-3-4-5-8,總長度為19。注意FGD為了從城市2到城市4可以路過城市3,但不在城市3停留。這樣就不違反FGD的要求了。并且由于FGD想要走最短的路徑,因此這個方案正是FGD需要的。輸入
第一行包含3個整數N(2<=N<=20000),M(1<=M<=200000),K(0<=K<=20),意義如上所述。輸出
只包含一行,包含一個整數,表示最短的旅行距離。輸入示例
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 longint 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; }?
轉載于:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6726013.html
總結
以上是生活随笔為你收集整理的[BZOJ1097][POI2007]旅游景点atr的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VK Cup 2017 - Round
- 下一篇: 概率检索模型:BIM+BM25+BM25