但这个问题的难点就在它要限制在每个城市的警察数量(cops)不超过k的前提下的最短路,一开始没什么思路,一些方法因为有些方面不足也都被摒弃了。这是应该想着去对Floyd加以改动,使之适合这一题,我们都知道Floyd的第一层(for(k=0;k<n;k++))是按照从第1个节点到第N个节点的顺序来更新的,当更新到第k个节点时所得到的最短路径d[i][j]是i到j由前k个结点所组成的最短路径,这时不一定是全局最优的最短路径,但是肯定是由前k个城市组成的最短路径。以此为契机,先把每个城市的cops按照从小到大的顺序排序,Floyd的第一层按照cops从小到大来更新ans[k][i][j],ans[k][i][j]表示前k个结点更新出来的从i到j的最短路径,如果cops[k]是小于等于给定限制的最大的城市里的cops,那么ans[k][i][j]就是query的答案。
对于每个query,使用upper_bound()函数可以得到第一个刚好小于等于cops[k]的地址,然后减去cops就是下标。在判断下ans[k][i][j]是否是给定的初始无穷大值就知道ans[k][i][j]是否是答案。
#include <iostream> #define MAX_INT 1073741823 using namespace std; int n,m,d[202][202]; int pos[202],cops[202]; int ans[202][202][202]; inline bool cmp(int i,int j) { return cops[i]<cops[j]; } void readin(void) { int i,j,u,v,k,query; cin >> n >> m; for(i=0;i<n;i++) { cin >> cops[i]; pos[i]=i; } for(i=0; i<n; i++) for(j=0; j<n; j++) if(i==j) d[i][j]=0; else d[i][j]=MAX_INT; for(i=0; i<m; i++) { cin >> u >> v >> k; d[u][v]=d[v][u]=k; } sort(pos,pos+n,cmp); for(i=0; i<n; i++) for(j=0; j<n; j++) ans[0][i][j] = d[i][j]; for(k=0; k<n; k++) { v=pos[k]; for(i=0; i<n; i++) for(j=0; j<n; j++) { ans[k+1][i][j]=ans[k][i][j]; if(ans[k+1][i][j]>ans[k][i][v]+ans[k][v][j]) ans[k+1][i][j]=ans[k][i][v]+ans[k][v][j]; } } sort(cops,cops+n); cin >> query; while(query--) { cin >> u >> v >> k; i=upper_bound(cops,cops+n,k)-cops; if(ans[i][u][v]>=MAX_INT) cout << -1 << endl; else cout << ans[i][u][v] << endl; } } int main() { int test; cin >> test; while(test--) { readin(); if(test) cout << endl; } return 0; }