题目
题意:
有一个图,节点为餐厅。道路边权为花费,餐厅有有花费,从某个点出发到某个点时,会选择花费最高度餐厅来消费。现在有Q个游览计划,对每个计划给出最小花费。
解法:
将餐厅按花费排序,然后依次做SPFA,表示以此餐厅为路上最高花费的餐厅。所以SPFA的时候更高价格的餐厅就不扩展。
Time:469ms Memory:47836KB Length:3327B #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <string> #include <vector> #include <map> #include <queue> #include <set> #include <sstream> #define DBLE 1e-8 #define PI 3.1415926535898 #define INF (100000000000000LL) #define MAXM 40010 #define MAXN 1010 #define MP(x,y) (make_pair((x),(y))) #define FI first #define SE second using namespace std; int nw[MAXN]; int he[MAXN],to[MAXM],nex[MAXM],len[MAXM],top; long long dis[MAXN],ans[MAXM]; //set<pair<long long,int> > se; int n,m, Q; bool vis[MAXN]; int qa[20010], qb[20010]; void add(int a,int b,int c) { nex[top]=he[a]; to[top]=b; len[top]=c; he[a]=top++; } int q[1000005]; void spfa(int h) { q[1]=h; int head=1, tail=1; for (int i=1; i<=n; i++) { vis[i]=0; dis[i]=INF; } dis[h]=0; while (head<=tail) { int u=q[head++]; vis[u]=0; for (int i=he[u]; i!=-1; i=nex[i]) { int v=to[i]; if (nw[v]>nw[h]) continue; if (dis[v]>dis[u]+len[i]) { dis[v]=dis[u]+len[i]; if (!vis[v]) { vis[v]=1; q[++tail]=v; } } } } for (int i=1; i<=Q; i++) { int u=qa[i], v=qb[i]; if (dis[u]<INF && dis[v]<INF ) ans[i]=min(ans[i], dis[u]+dis[v]+nw[h]); } } int main() { //freopen("J:\\MyDocument\\Code\\input.txt","r",stdin); while(scanf("%d%d",&n,&m)&&(n||m)) { memset(he,-1,sizeof(he)); top=0; for(int i=1;i<=n;++i) scanf("%d",&nw[i]); int a,b,c; for(int i=0;i<m;++i) scanf("%d%d%d",&a,&b,&c),add(a,b,c),add(b,a,c); scanf("%d",&Q); for (int i=1; i<=Q; i++) { scanf("%d %d", &qa[i], &qb[i]); ans[i]=INF; } for(int i=1;i<=n;++i) spfa(i); for (int i=1; i<=Q; i++) { if (ans[i]>=INF) ans[i]=-1; printf("%I64d\n", ans[i]); } printf("\n"); } return 0; }