P4779 【模板】单源最短路径(标准版)
思路
堆优化的dijkstra模板
实现
#include <bits/stdc++.h>
using namespace std;
const int N = 500005;
typedef pair<int, int> PII;
int n,m,start;
int h[N], w[N], e[N], ne[N], idx;
int dist[N];
bool st[N];
void add(int a, int b,int we)
{
e[idx] = b, w[idx] = we,ne[idx] = h[a], h[a] = idx ++ ;
}
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[start] = 0;
priority_queue<PII, vector<PII>, greater<PII>> heap;
heap.push({0, start}); // first存储距离,second存储节点编号
while (heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
if (dist[j] > distance + w[i])
{
dist[j] = distance + w[i];
heap.push({dist[j], j});
}
}
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
int main()
{
idx = 0;
memset(h, -1, sizeof h);
cin>>n>>m>>start;
int t1,t2,t3;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&t1,&t2,&t3);
add(t1,t2,t3);
}
dijkstra();
for(int i=1;i<=n;i++)
{
if(dist[i]!=0x3f3f3f3f) cout<<dist[i]<<" ";
else cout<<2147483647<<" ";
}
}
P1629 邮递员送信
思路
建反图 两次dijkstra
实现
#include <bits/stdc++.h>
using namespace std;
const int N = 500005;
typedef pair<int, int> PII;
int n,m;
int h[N<<1], w[N<<1], e[N<<1], ne[N<<1], idx;
int dist[N];
bool st[N];
void add(int a, int b,int we)
{
e[idx] = b, w[idx] = we,ne[idx] = h[a], h[a] = idx ++ ;
}
int dijkstra(int start)
{
memset(dist, 0x3f, sizeof dist);
dist[start] = 0;
priority_queue<PII, vector<PII>, greater<PII>> heap;
heap.push({0, start}); // first存储距离,second存储节点编号
while (heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
if (dist[j] > distance + w[i])
{
dist[j] = distance + w[i];
heap.push({dist[j], j});
}
}
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
int main()
{
idx = 0;
memset(h, -1, sizeof h);
cin>>n>>m;
int t1,t2,t3;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&t1,&t2,&t3);
add(t1,t2,t3);
add(t2+n,t1+n,t3);
}
long long ans = 0;
dijkstra(1);
for(int i=2;i<=n;i++)
ans+=dist[i];
dijkstra(1+n);
for(int i=2+n;i<=2*n;i++)
ans+=dist[i];
cout<<ans;
}
P1144 最短路计数
思路
由于是无向无权图,所以只要在bfs的同时计数即可~
- 如果i点被访问过且本次bfs的距离与记录的最短距离dist相等 则nums[i]+=nums[father],i点被访问过因此不进行push操作
- 如果i点未被访问,则做最短路更新和push操作
- 重边算作两条不同的边 是需要被记录的 自环直接删除即可
实现
#include <bits/stdc++.h>
using namespace std;
const int N = 1000005;
int n,m;
vector<int> a[N];
int dist[N],nums[N];
bool vis[N];
typedef pair<int, int> PII;
int main()
{
int x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
if(x!=y)
{
a[x].push_back(y);
a[y].push_back(x);
}
}
for(int i=1;i<=n;i++)
dist[i] = 2147483647;
queue<PII> q;
q.push({0,1});
dist[1] = 0;
nums[1] = 1;
while(q.size())
{
auto t = q.front();
q.pop();
int d = t.first;
int node = t.second;
//cout<<node<<" "<<d<<endl;
for(int i=0;i<a[node].size();i++)
{
if(vis[a[node][i]])
{
if(d+1==dist[a[node][i]])
{
nums[a[node][i]]+=nums[node];
nums[a[node][i]]%=100003;
}
continue;
}
if(d+1<dist[a[node][i]])
{
dist[a[node][i]] = d+1;
nums[a[node][i]] = nums[node];
nums[a[node][i]]%=100003;
}
q.push({d+1,a[node][i]});
vis[a[node][i]] = 1;
}
}
for(int i=1;i<=n;i++)
cout<<nums[i]%100003<<endl;
}
P1119 灾后重建
思路
floyd算法中
f
[
k
]
[
i
]
[
j
]
f[k][i][j]
f[k][i][j]的含义是:以
i
,
j
i,j
i,j为起点和终点,路径上的中间点编号不超过
k
k
k的最短距离。
本题中村庄重建的时间点是单调的,就可以预处理出floyd数组,查询时直接输出
实现
来自洛谷题解区 Dog_Two
#include<bits/stdc++.h>
using namespace std;
const int maxn=200+10;
int n,m,q;
int fix[maxn];
int dis[maxn][maxn][maxn];
void read(){
cin>>n>>m;
for(int i=0;i<n;++i) scanf("%d",&fix[i]);
memset(dis,0x3f,sizeof(dis));
for(int i=1;i<=m;++i){
int u,v,w; scanf("%d%d%d",&u,&v,&w);
dis[0][u][v]=dis[0][v][u]=w;
}
}
//对于原始的floyd算法,f[k][i][j]的含义是:
//以i,j为起点和终点,路径上的中间点编号不超过k的最短距离。
void prework(){
for(int i=0;i<n;++i) dis[0][i][i]=0;
for(int i=0;i<n;++i)
for(int j=0;j<n;++j)
dis[0][i][j]=min(dis[0][i][j],dis[0][i][0]+dis[0][0][j]);
for(int k=1;k<n;++k)
for(int i=0;i<n;++i)
for(int j=0;j<n;++j)
dis[k][i][j]=min(dis[k-1][i][j],dis[k-1][i][k]+dis[k-1][k][j]);
}
void solve(){
cin>>q;
for(int i=1;i<=q;++i){
int u,v,t; scanf("%d%d%d",&u,&v,&t);
int _t=upper_bound(fix,fix+n,t)-fix-1;
printf("%d\n",t<fix[u] or t<fix[v] or dis[_t][u][v]==0x3f3f3f3f?-1:dis[_t][u][v]);
}
}
int main(){
read();
prework();
solve();
return 0;
}
欢迎指正