【BZOJ 3445】【Usaco2014 Feb】Roadblock

http://www.lydsy.com/JudgeOnline/problem.php?id=3445
加倍的边一定在最短路上(否则继续走最短路)。
最短路长度是O(n)的,暴力扫最短路上的每条边,再暴力dijkstra,时间复杂度\(O(n^3)\)
话说堆优dij的复杂度到底多少?\(O((n+m)logn)\)\(O(nlogn+m)\)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 253;

int a[N][N], n, m, now, pre[N];
ll dist[N], shortest, t;
bool vis[N];

int main() {
	int u, v, e;
	memset(a, -1, sizeof(a));
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; ++i) {
		scanf("%d%d%d", &u, &v, &e);
		a[u][v] = a[v][u] = e;
	}
	
	memset(dist, 127, sizeof(ll) * (n + 1));
	dist[1] = 0;
	for (int i = 1; i <= n; ++i) {
		now = -1;
		for (int j = 1; j <= n; ++j)
			if (!vis[j] && ((dist[j] < dist[now]) || (now == -1)))
				now = j;
		if (now == -1) break;
		for (int j = 1; j <= n; ++j)
			if (!vis[j] && a[now][j] != -1 && (t = (dist[now] + a[now][j])) < dist[j]) {
				dist[j] = t;
				pre[j] = now;
			}
		vis[now] = true;
	}
	
	shortest = dist[n];
	int tmp = n; ll ans = shortest;
	while (tmp != 1) {
		a[pre[tmp]][tmp] <<= 1;
		a[tmp][pre[tmp]] <<= 1;
		
		memset(dist, 127, sizeof(ll) * (n + 1));
		memset(vis, 0, sizeof(bool) * (n + 1));
		dist[1] = 0;
		for (int i = 1; i <= n; ++i) {
			now = -1;
			for (int j = 1; j <= n; ++j)
				if (!vis[j] && ((dist[j] < dist[now]) || (now == -1)))
					now = j;
			if (now == -1) break;
			for (int j = 1; j <= n; ++j)
				if (!vis[j] && a[now][j] != -1 && (t = (dist[now] + a[now][j])) < dist[j])
					dist[j] = t;
			vis[now] = true;
		}
		
		ans = max(ans, dist[n]);
		a[pre[tmp]][tmp] >>= 1;
		a[tmp][pre[tmp]] >>= 1;
		tmp = pre[tmp];
	}
	
	printf("%lld\n", ans - shortest);
	return 0;
}
posted @ 2016-11-16 14:51  abclzr  阅读(382)  评论(0编辑  收藏  举报