【最短路】HDOJ 2363 Cycling

二分+枚举+最短路。。。不错的题。。。

#include <iostream>
#include <queue> 
#include <stack> 
#include <map> 
#include <set> 
#include <bitset> 
#include <cstdio> 
#include <algorithm> 
#include <cstring> 
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 105
#define maxm 10005
#define eps 1e-10
#define mod 1000000007
#define INF 1e9+10
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid 
#define rson o<<1 | 1, mid+1, R 
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;

struct Edge
{
	int v, c;
	Edge *next;
}pool[maxm], *edges, *H[maxn];

struct node
{
	int id, d;
	bool operator < (const node& b) const {
		return d > b.d;
	}
}now, tmp;
priority_queue<node> q;
int dist[maxn], vis[maxn];
int h[maxn], hh[maxn];
int n, m;

void addedges(int u, int v, int c)
{
	edges->v = v;
	edges->c = c;
	edges->next = H[u];
	H[u] = edges++;
}

void init(void)
{
	edges = pool;
	memset(H, 0, sizeof H);
}

int cmp(int a, int b)
{
	return a < b;
}

void read(void)
{
	int a, b, c;
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i++) scanf("%d", &h[i]), hh[i] = h[i];
	for(int i = 1; i <= m; i++) {
		scanf("%d%d%d", &a, &b, &c);
		addedges(a, b, c);
		addedges(b, a, c);
	}
	sort(h+1, h+n+1, cmp);
}

int dijstra(int s, int low, int high)
{
	for(int i = 1; i <= n; i++) dist[i] = INF, vis[i] = 0;
	tmp.id = s, tmp.d = 0;
	if(hh[s] >= low && hh[s] <= high) q.push(tmp);
	dist[s] = 0;

	while(!q.empty()) {
		now = q.top(), q.pop();
		int x = now.id, d = now.d;
		if(vis[x]) continue;
		vis[x] = 1;
		for(Edge *e = H[x]; e; e = e->next) {
			if(dist[e->v] > dist[x] + e->c && hh[e->v] >= low && hh[e->v] <= high) {
				dist[e->v] = dist[x] + e->c;
				tmp.id = e->v, tmp.d = dist[e->v];
				q.push(tmp);
			}
		}
	}

	return dist[n];
}

void work(void)
{
	int top, bot, low, mid, res, ans = h[n], t;
	for(int i = 1; i <= n; i++) {
		low = h[i], top = h[n], bot = h[i], res = -1;
		//printf("AAA %d\n", i);
		//printf("%d %d\n", dijstra(1, 3, 5), dist[n]);
		while(top >= bot) {
			mid = (top + bot) >> 1;
			if(dijstra(1, low, mid) != INF) res = mid, top = mid-1;
			else bot = mid+1;
		}
		if(res != -1 && res - low <= ans) {
			if(res - low < ans) ans = res - low, t = dijstra(1, low, res);
			else t = min(t, dijstra(1, low, res));
		}
	}
	
	printf("%d %d\n", ans, t);
}

int main(void)
{
	int _;
	while(scanf("%d", &_)!=EOF) {
		while(_--) {
			init();
			read();
			work();
		}
	}

	return 0;
}


你可能感兴趣的:(HDU)