HDU 3873 必须写一个解题报告,很神奇的最短路
2011-07-25 19:16
323 查看
此题就是要求一个最短路,但是有一个约束条件:到达该点的时间以前必然可以到达某些保护他的节点(protect(i)表示)。借来70学长的代码观摩了一下。发现时用队列和优先队列迭代求最短路以及达到题目要求的。
首先设计标记chk[i] = 0 , 1, 2 0表示没占领且没达到,1表示达到了但是没有占领,2表示占领了改该节点。
对于每个点记录一下几个值
1. dist[i] 已经被从1开始一次占领若干节点最后占领i节点的最短距离。dist[i] = min(dist[pre] + value[pre][i]);
2. maxn[i] 表示占领所有保护他的节点的的时间的最大值。 maxn[i] = max(ans[u] u属于proctect(i))
3. ans[i] 表示占领i节点的最短时间。
可以得到ans[i] = max(dist[i], maxn[i]);
然后用队列和优先队列进行处理
每次只有chk[i] == 2的点如对,并对i保护的点除去保护deg[i]--;然后所以未求出最短路且未占领的点松弛送入优先队列。只是队列空为止。然后在优先队列里。松弛节点记录dist[i] 。如果优先队列里的节点还有deg(还被保护着),则标记chk[i] = 1;否则ans[i] = max(dist[i], maxn[i])(这里其实取的就是dist[i],因为maxn[i]一定比dist[i]大,他还在堆里要不就还没进堆呢……)。最后chk[i] == 1的如何处理呢?如果chk[i] == 1且除去保护点的过程中发现deg[i] == 0了,就可以ans[i] = max(dist[i], maxn[i])(其实这里取的就是maxn[i],原因你懂的)
代码如下:
hdu 3873
首先设计标记chk[i] = 0 , 1, 2 0表示没占领且没达到,1表示达到了但是没有占领,2表示占领了改该节点。
对于每个点记录一下几个值
1. dist[i] 已经被从1开始一次占领若干节点最后占领i节点的最短距离。dist[i] = min(dist[pre] + value[pre][i]);
2. maxn[i] 表示占领所有保护他的节点的的时间的最大值。 maxn[i] = max(ans[u] u属于proctect(i))
3. ans[i] 表示占领i节点的最短时间。
可以得到ans[i] = max(dist[i], maxn[i]);
然后用队列和优先队列进行处理
每次只有chk[i] == 2的点如对,并对i保护的点除去保护deg[i]--;然后所以未求出最短路且未占领的点松弛送入优先队列。只是队列空为止。然后在优先队列里。松弛节点记录dist[i] 。如果优先队列里的节点还有deg(还被保护着),则标记chk[i] = 1;否则ans[i] = max(dist[i], maxn[i])(这里其实取的就是dist[i],因为maxn[i]一定比dist[i]大,他还在堆里要不就还没进堆呢……)。最后chk[i] == 1的如何处理呢?如果chk[i] == 1且除去保护点的过程中发现deg[i] == 0了,就可以ans[i] = max(dist[i], maxn[i])(其实这里取的就是maxn[i],原因你懂的)
代码如下:
hdu 3873
#include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <queue> #define FOREACH(i, con) for(__typeof(con.begin()) i = con.begin();i != con.end();++i) #define CC(con, i) memset(con, i, sizeof(con)) using namespace std; typedef long long LL; const int N = 3000; const LL INF = 1ll << 40; LL dist , maxn , ans ; int deg , chk ; vector<pair<int, LL> > g ; vector<int> lmt ; struct status { long long d; int v; bool operator < (const status& a) const { return d > a.d; } status(int v = 0, long long d = 0) { this->d = d; this->v = v; } }; int main() { int t, n, m; scanf("%d", &t); while(t-- && scanf("%d %d", &n, &m) == 2) { int a, b; LL val; for(int i = 0; i < n; i++) g[i].clear(); for(int i = 0; i < n; i++) lmt[i].clear(); CC(deg, 0); for(int i = 0; i < m; i++) { scanf("%d %d %I64d", &a, &b, &val); a--, b--; g[a].push_back(make_pair(b, val)); } for(int i = 0; i < n; i++) { scanf("%d", °[i]); for(int j = 0; j < deg[i]; j++) { scanf("%d", &a); a--; lmt[a].push_back(i); } } queue<int> q; priority_queue<status> pq; CC(maxn, 0);CC(chk, 0); fill(ans, ans + n, INF); fill(dist, dist + n, INF); q.push(0); chk[0] = 2; maxn[0] = ans[0] = dist[0] = 0; //chk[i] == 2进队 while(!q.empty() || !pq.empty()) { while(!q.empty()) { int v = q.front(); q.pop(); FOREACH(i, lmt[v]) { deg[*i]--; maxn[*i] = max(maxn[*i], ans[v]); if(chk[*i] == 1 && deg[*i] == 0) { ans[*i] = max(dist[*i], maxn[*i]); q.push(*i); chk[*i] = 2; } } FOREACH(i, g[v]) if(chk[i->first] == 0) pq.push(status(i->first, ans[v] + i->second)); } while(!pq.empty()) { status beg = pq.top(); pq.pop(); if(!chk[beg.v]) { dist[beg.v] = beg.d; if(deg[beg.v] == 0) { ans[beg.v] = max(dist[beg.v], maxn[beg.v]); chk[beg.v] = 2; q.push(beg.v); break; } else chk[beg.v] = 1; } } } printf("%I64d\n", ans[n - 1]); } return 0; }
相关文章推荐
- HDU 3339 In Action 解题报告(最短路+背包)
- hdu 2544 最短路 Bellman_Ford 解题报告
- hdu 1142 A Walk Through the Forest 最短路+记忆化搜索 解题报告
- hdu 2544 最短路 spfa 解题报告
- hdu 2680 Choose the best route 最短路 解题报告
- hdu 2066 一个人的旅行 最短路 dijkstra 解题报告
- hdu 2544 最短路 解题报告
- hdu 5418 Victor and World 最短路 floyd 解题报告
- Hdu 3986 【枚举】【最短路】 解题报告
- HDU 3339 In Action 解题报告(最短路+背包)
- hdu 1598 解题报告
- 解题报告:HDU_6169 Senior PanⅡ (记忆化搜索)
- 2012 Multi-University Training Contest 9 1009解题报告 HDU 4388
- hdu 1963 Investment 解题报告
- HDU 2001 计算两点间的距离 解题报告
- CDOJ 30 最短路 解题报告
- HDU 3732 Ahui Writes Word 解题报告
- HDU解题报告——1019
- 杭电acm1017 hdu-acm-1017解题报告
- hdu 3631 Shortest Path floyd 解题报告