BZOJ1922: [Sdoi2010]大陆争霸

由于本人头铁,这题搞了将近一上午还是爆零

于是颓题解

对于每个点分别记录两个值:到达这个点的最短时间 和 进入这个点的最短时间

前一个值用最短路更新,后一个值用保护它的点的最短路更新

所以本题中一个点的最短路就是 上边的两个值取 max

按题目的道理大力更新最短路即可


代码:

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<queue>
using namespace std;

const int MAXN = 3005, MAXM = 70005;

struct EDGE{
	int nxt, to, val;
	EDGE(int NXT = 0, int TO = 0, int VAL = 0) {nxt = NXT; to = TO; val = VAL;}
}edge[MAXM << 1];
int n, m, totedge;
int head[MAXN], rem[MAXN], d1[MAXN], d2[MAXN];
bool vis[MAXN], pro[MAXN], to[MAXN];
priority_queue<pair<int,int> > q;

inline void add(int x, int y, int v) {
	edge[++totedge] = EDGE(head[x], y, v);
	head[x] = totedge;
	return;
}
inline void dij() {
	d1[1] = d2[1] = 0;
	to[1] = true;
	q.push(make_pair(0, 1));
	while(!q.empty()) {
		int x = q.top().second; q.pop();
		if(vis[x]) continue;
		vis[x] = true;
		int cur = max(d1[x], d2[x]);
		for(int i = head[x]; i; i = edge[i].nxt) {
			int y = edge[i].to;
			if(edge[i].val != 0x3f3f3f3f) {
				if(d1[y] > cur + edge[i].val) {
					to[y] = true;
					d1[y] = cur + edge[i].val;
					if(!rem[y]) q.push(make_pair(-max(d1[y], d2[y]), y));
				}
			} else {
				--rem[y];
				if(!rem[y]) {
					d2[y] = cur;
					if(to[y]) q.push(make_pair(-max(d1[y], d2[y]), y));
				}
			}
		} 
	}
	return;
}

int main() {
	scanf("%d%d", &n, &m);
	register int xx, yy, vv;
	for(int i = 1; i <= m; ++i) {
		scanf("%d%d%d", &xx, &yy, &vv);
		if(xx == yy) continue;
		add(xx, yy, vv);
	}
	for(int i = 1; i <= n; ++i) {
		d1[i] = 0x3f3f3f3f;
		d2[i] = 0;
		scanf("%d", &vv);
		rem[i] += vv;
		pro[i] = vv;
		while(vv--) {
			d2[i] = 0;
			scanf("%d", &xx);
			add(xx, i, 0x3f3f3f3f);
		}
	}
	dij();
	printf("%d\n", max(d1[n], d2[n]));
	return 0;
}

  

posted @ 2018-09-05 15:19  EvalonXing  阅读(198)  评论(0编辑  收藏  举报