洛谷P2446 大陆争霸

这是一道dijkstra拓展......不知道为什么被评成了紫题。

有一个很朴素的想法就是每次松弛的时候判断一下那个点是否被保护。如果被保护就不入队。

然后发现写起来要改的地方巨多无比......

改到最后应该是用2/3个数组,分别表示最早可达时间(time),最早无防护时间(ruin)。以及一个取它们最大值的数组(ed),表示真实摧毁时间。

然后每次当一个点被某种更新之后入度变成0了,就用ed入队。

如果一个点出队了,就vis,然后不可被更新,然后更新某些点的入度,ruin和time。

这个正确性应该是有的:此后更新的每个点的ed都不会比当前点的ed小。

代码上两种更新的先后顺序不会影响结果。

 #include <cstdio>
#include <queue>
#include <algorithm>
#define mp std::make_pair typedef long long LL;
const int N = , M = ;
const LL INF = 1ll << ; struct Edge {
int nex, v;
LL len;
}edge[M << ], _edge[M << ]; int top, _top; int e[N], _e[N], n, in[N];
bool vis[N];
LL time[N], ruin[N], ed[N]; inline void add(int x, int y, LL z) {
top++;
edge[top].v = y;
edge[top].len = z;
edge[top].nex = e[x];
e[x] = top;
return;
} inline void _add(int x, int y) {
_top++;
_edge[_top].v = y;
_edge[_top].nex = _e[x];
_e[x] = _top;
return;
} std::priority_queue<std::pair<LL, int> > Q; inline void BFS() { Q.push(mp(-, ));
ed[] = ;
ruin[] = ;
time[] = ; int x;
while(!Q.empty()) {
x = Q.top().second;
Q.pop();
if(vis[x]) {
continue;
}
vis[x] = ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(vis[y]) {
continue;
}
if(time[y] > ed[x] + edge[i].len) {
time[y] = ed[x] + edge[i].len;
if(!in[y]) {
ed[y] = std::max(ruin[y], time[y]);
Q.push(mp(-ed[y], y));
}
}
} for(int i = _e[x]; i; i = _edge[i].nex) {
int y = _edge[i].v;
in[y]--;
ruin[y] = std::max(ruin[y], ed[x]);
if(!in[y]) {
ed[y] = std::max(ruin[y], time[y]);
Q.push(mp(-ed[y], y));
}
}
} if(ruin[n] >= INF) {
printf("Mission Failed");
return;
}
printf("%lld", std::max(ruin[n], time[n]) - ); /*for(int i = 1; i <= n; i++) {
printf("%d ruin = %lld time = %lld \n", i, ruin[i], time[i]);
}
puts("");*/ return;
} int main() {
//freopen("bomb.in", "r", stdin);
//freopen("bomb.out", "w", stdout); int m;
scanf("%d%d", &n, &m);
for(int i = , x, y; i <= m; i++) {
LL z;
scanf("%d%d%lld", &x, &y, &z);
add(x, y, z);
//add(y, x, z);
}
for(int i = , k, x; i <= n; i++) {
scanf("%d", &k);
for(int j = ; j <= k; j++) {
scanf("%d", &x);
_add(x, i);
in[i]++;
}
time[i] = INF;
}
time[n] = INF; BFS(); /*puts("");
for(int i = 1; i <= n; i++) {
printf("%d ruin = %lld time = %lld \n", i, ruin[i], *(time + i));
}*/ return ;
}

AC代码

上一篇:移动跨平台开发框架Ionic开发一个新闻阅读APP


下一篇:《C++编程思想》第二章 数 据 抽 象(原书代码+习题+答案)