二分+枚举+最短路。。。不错的题。。。
#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; }