最短路相关题目
1.luoguP1807 最长路_NOI导刊2010提高(07)
思路:
求最长路,其实跟最短路是一毛一样的,跑一边spfa就好。我们只需要加点小优化:在存边的时候把w存为-w,然后最后输出的时候输出-dis[n]就好
坑点:
这是一个有向图,不是无向图
上代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <queue> #include <cstring> using namespace std; const int N = 1501; const int M = 50001; int n,m; struct node { int next,to,w; } e[M<<1]; int top,head[N]; void add(int u,int v,int w) { top++; e[top].to=v; e[top].w=w; e[top].next=head[u]; head[u]=top; } queue<int>q; int dis[N]; bool flag,vis[N]; void spfa() { memset(dis,0x7f,sizeof(dis)); q.push(1); vis[1]=true; dis[1]=0; while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=false; for(int i=head[u],v,w; i; i=e[i].next) { v=e[i].to,w=e[i].w; if(dis[u]+w<dis[v]) { dis[v]=dis[u]+w; if(!vis[v]) { vis[v]=true; q.push(v); } if(v==n) flag=true; } } } } int main() { scanf("%d%d",&n,&m); for(int i=1,u,v,w; i<=m; i++) { scanf("%d%d%d",&u,&v,&w); add(u,v,-w); } spfa(); if(!flag) printf("-1"); else printf("%d",-dis[n]); return 0; }
2.P1119 灾后重建
思路:
出题人超良心的帮我们把询问按时间顺序排序了,那我们就不需要vis数组记录每个点是否已经做过Floyd,只要每次读入的时候把之前的时间没处理过的全部处理一遍就可以。
坑点:
注意该题的初始化!其实要说的话应该是注意所有的Floyd的初始化,因为我们要用到dis[i][k]+dis[k][j],所以如果memset0x7f的话会有可能炸出负数来,那样的话Floyd就不准了,所以我们在进行初始化的时候最好是要初始化(memset)为0x3f才可以
上代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #define INF 0x3f3f3f3f using namespace std; const int M = 50015; const int N = 233; int n,m,Q,k; int dis[N][N],t[M]; int main() { scanf("%d%d",&n,&m); memset(t,0x3f,sizeof(t)); memset(dis,0x3f,sizeof(dis)); for(int i=0; i<n; i++) scanf("%d",&t[i]),dis[i][i]=0; for(int i=1,u,v,w; i<=m; i++) { scanf("%d%d%d",&u,&v,&w); dis[u][v]=dis[v][u]=w; } scanf("%d",&Q); for(int x=1,u,v,c; x<=Q; x++) { scanf("%d%d%d",&u,&v,&c); //注意这里的k是不需要进行清零的,具体原因嘛,那就是因为良心的出题人啦 while(t[k]<=c) { for(int i=0; i<n; i++) for(int j=0; j<n; j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); k++; } //宏定义的INF就等价于memset的数 //所以dis[u][v]==INF就说明两点之间并没有进行联通 //而t[u]以及t[v] >c则是端点并没有建好的情况 if(dis[u][v]==INF || t[u]>c || t[v]>c) printf("-1\n"); else printf("%d\n",dis[u][v]); } return 0; }