2018 宁夏省赛 F. Moving On
题目链接 https://nanti.jisuanke.com/t/28406
大意是 有n(<=200)个城市,城市间有路(Input给了邻接矩阵) 每个城市有一个危险值,然后是q(2e4)个询问,每个询问给了 u,v ,w ,对于每个询问回答u到v的最短路长度(最短路过程中不得经过危险值超过w的城市,ps不含首尾)
开始看见邻接矩阵的形式猜了用Floyd写,想的是每次询问跑一次最短路(循环k时避过危险值超过w的点),但q有2e4,会TLE;后来又想每次询问跑一遍Dijkstra(改造后的不经过危险值超出的点),以为Dijkstra能快一点,但还是TLE了。
正确的做法还是Floyd,按危险值从小到大排序城市编号(间接排序),然后用的dp[][][]记录最短路。
dp[k][i][j]表示 添加(第1~k小的危险值的城市后)的 i->j 最短路。(其实就是Floyd三维未降维的版本)
然后针对每个询问找到它的最大k 的最短路图。
1 #include<bits/stdc++.h> 2 #define EPS 1e-9 3 using namespace std; 4 5 typedef long long ll; 6 const int INF=0x3f3f3f3f; 7 const int MAXN=211; 8 9 int rob[211]; 10 int dp[211][211][211]; 11 int id[211]; 12 13 bool cmp(int i,int j){ 14 return rob[i]<rob[j]; 15 } 16 17 int main(){ 18 int Tests; 19 scanf("%d",&Tests); 20 for(int cntT=1;cntT<=Tests;++cntT){ 21 memset(dp,INF,sizeof(dp)); 22 int N,Q; 23 scanf("%d%d",&N,&Q); 24 for(int i=1;i<=N;++i){ 25 id[i]=i; 26 scanf("%d",&rob[i]); 27 } 28 sort(id+1,id+N+1,cmp); 29 30 for(int i=1;i<=N;++i) 31 for(int j=1;j<=N;++j) 32 scanf("%d",&dp[0][i][j]); 33 for(int k=1;k<=N;++k){ 34 int rk=id[k]; 35 for(int i=1;i<=N;++i) 36 for(int j=1;j<=N;++j) { 37 dp[k][i][j]=min(dp[k-1][i][j],dp[k-1][i][rk]+dp[k-1][rk][j]); 38 } 39 } 40 printf("Case #%d:\n",cntT); 41 for(int q=1;q<=Q;++q){ 42 int u,v,dan; 43 scanf("%d%d%d",&u,&v,&dan); 44 int k=0; 45 for(int i=1;i<=N;++i) 46 if(rob[id[i]]<=dan) k=i; 47 printf("%d\n",dp[k][u][v]); 48 } 49 } 50 return 0; 51 }
主要是熟悉Floyd原型。
posted on 2018-07-17 19:23 Emiya_Kiritsugu 阅读(807) 评论(0) 编辑 收藏 举报