堆优化的dijkstra
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5+10,M=2*N;
int h[N],e[M],ne[M],w[M],idx;
int n,m,s;
int dist[M],st[M];
void add(int a,int b,int c)
{
e[idx]=b;w[idx]=c;ne[idx]=h[a];h[a]=idx++;
}
void dij()
{
memset(dist,0x3f,sizeof(dist));
dist[s]=0;
priority_queue<PII,vector<PII>,greater<PII> > heap;
heap.push({0,s});
while(heap.size())//
{
auto t=heap.top();
heap.pop();
int vec=t.second;
if(st[vec])continue;//
st[vec]=1;
for (int i = h[vec]; i!=-1; i=ne[i])
{
int j=e[i];
if(dist[j]>dist[vec]+w[i])//
{
dist[j]=dist[vec]+w[i];
heap.push({dist[j],j});
}
}
}
}
int main()
{
memset(h, -1, sizeof h);
cin>>n>>m>>s;
while (m -- ){
int a,b,c;
cin>>a>>b>>c;
add(a, b, c);
}
dij();
for (int i = 1; i <= n; i ++ )
{
cout<<dist[i]<<" ";
}
return 0;
}
P1629 邮递员送信
求从1到其他点的最小距离和其他点到1的最小距离,对于后者我们需要进行反向建图,之后按照模板再改一遍。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=100010 , M=500010;
typedef long long ll;
typedef pair<int,int> pii;
int dist[N];
int h[N],e[M],ne[M],idx,w[M];
int hr[N];
void add(int h[],int a,int b,int c)
{
e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
int n,m,s;
bool st[N];
void dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[1]=0;
priority_queue<pii,vector<pii>,greater<pii> >q;
q.push({0,1});
while(q.size())
{
pii t=q.top();
q.pop();
int ver=t.second,dis=t.first;
if(st[ver]) continue;
st[ver]=true;
for(int i=h[ver];~i;i=ne[i])
{
int j=e[i];
if(dist[j]>dist[ver]+w[i]){
dist[j]=dist[ver]+w[i];
q.push({dist[j],j});
}
}
}
ll res=0;
for(int i=1;i<=n;i++)
res+=dist[i];
memset(dist,0x3f,sizeof dist);
dist[1]=0;
priority_queue<pii,vector<pii>,greater<pii> >qq;
qq.push({0,1});
memset(st,0,sizeof st);
while(qq.size())
{
pii t=qq.top();
qq.pop();
int ver=t.second,dis=t.first;
if(st[ver]) continue;
st[ver]=true;
for(int i=hr[ver];~i;i=ne[i])
{
int j=e[i];
if(dist[j]>dist[ver]+w[i]){
dist[j]=dist[ver]+w[i];
qq.push({dist[j],j});
}
}
}
for(int i=1;i<=n;i++)
res+=dist[i];
cout<<res<<endl;
return;
}
int main()
{
memset(h,-1,sizeof h);
memset(hr,-1,sizeof hr);
cin>>n>>m;
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
add(h,a,b,c);
add(hr,b,a,c);
}
dijkstra();
}
SPFA
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5+10,M=2*N;
int h[N],e[M],ne[M],w[M],idx;
int n,m,s;
int dist[M],st[M];
void add(int a,int b,int c)
{
e[idx]=b;w[idx]=c;ne[idx]=h[a];h[a]=idx++;
}
void spfa()
{
memset(dist,0x3f,sizeof dist);
dist[s]=0;
st[s]=1;
queue<int> q;
q.push(s);
while(q.size())
{
auto t=q.front();
q.pop();
st[t]=0;
for (int i = h[t]; i != -1; i = ne[i] )
{
int j=e[i];
if(dist[j]>dist[t]+w[i])
{
dist[j]=dist[t]+w[i];
if(!st[j])
{
q.push(j);
st[j]=1;
}
}
}
}
}
int main()
{
memset(h, -1, sizeof h);
cin>>n>>m>>s;
while (m -- ){
int a,b,c;
cin>>a>>b>>c;
add(a, b, c);
}
spfa();
for (int i = 1; i <= n; i ++ )
{
cout<<dist[i]<<" ";
}
return 0;
}
P1744 采购特价商品
模板题,就是注意距离带有小数点。
#include <bits/stdc++.h>
using namespace std;
#define debug(a) cout<<#a<<"="<<a<<endl;
#define all(a) begin(a), end(a)
#define pb(x) push_back(x)
typedef long long ll;
typedef pair<int,int> PII;
const int N=2000;
int t,n,m,ans,s=1;
int a[N],b[N];
int e[N],ne[N],h[N],idx;
double w[N],d[N];
int sa,en;
bool st[N];
void add(int a,int b,double c)
{
e[idx]=b;ne[idx]=h[a];w[idx]=c;h[a]=idx++;
}
void spfa()
{
for(int i=1;i<=n;i++)
{
d[i]=10000000;
}
queue<int> q;
d[sa]=0;
q.push(sa);
st[sa]=true;
while(q.size())
{
auto t=q.front();
q.pop();
st[t]=false;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(d[j]>d[t]+w[i])
{
d[j]=d[t]+w[i];
if(st[j]==false)
{
q.push(j);
st[j]=true;
}
}
}
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
memset(h,-1,sizeof h);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i]>>b[i];
}
cin>>m;
while(m--)
{
int x,y;
cin>>x>>y;
double dd=sqrt((a[x]-a[y])*(a[x]-a[y])+(b[x]-b[y])*(b[x]-b[y]));
add(x,y,dd);add(y,x,dd);
}
cin>>sa>>en;
spfa();
printf("%.2f",d[en]);
return 0;
}
P1807 最长路
对于求最长路,我们把带权边的权值取反,然后用SPFA来跑,最后把答案取反
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 5e5+10,M=2*N;
int h[N],e[M],ne[M],w[M],idx;
int n,m,s=1;
int dist[M],st[M];
void add(int a,int b,int c)
{
e[idx]=b;w[idx]=c;ne[idx]=h[a];h[a]=idx++;
}
void spfa()
{
memset(dist,0x3f,sizeof dist);
dist[s]=0;
st[s]=1;
queue<int> q;
q.push(s);
while(q.size())
{
auto t=q.front();
q.pop();
st[t]=0;
for (int i = h[t]; i != -1; i = ne[i] )
{
int j=e[i];
if(dist[j]>dist[t]+w[i])
{
dist[j]=dist[t]+w[i];
if(!st[j])
{
q.push(j);
st[j]=1;
}
}
}
}
}
int main()
{
memset(h, -1, sizeof h);
cin>>n>>m;
while (m -- ){
int a,b,c;
cin>>a>>b>>c;
add(a, b, -c);
}
spfa();
// for (int i = 1; i <= n; i ++ )
// {
// cout<<dist[i]<<" ";
// }
if(dist[n]==0x3f3f3f3f)
cout<<"-1";
else cout<<-dist[n];
return 0;
}
Floyd
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int M = 210,INF=1e9;
int g[M][M],dp[M][M];
int n,m,k;
void floyd(){
for (int k = 1; k <= n; k ++ )
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ ){
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}
}
int main()
{
cin>>n>>m>>k;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
if (i == j) g[i][j] = 0;
else g[i][j] = INF;
while (m -- )
{
int a,b,c;
cin>>a>>b>>c;
g[a][b]=min(g[a][b],c);
}
floyd();
while(k--){
int x,y;
cin>>x>>y;
int t=g[x][y];
if (t > INF / 2) puts("impossible");
else printf("%d\n", t);
}
return 0;
}
P2910 [USACO08OPEN] Clear And Present Danger S
很明显的多源最短路
#include <bits/stdc++.h>
using namespace std;
#define debug(a) cout<<#a<<"="<<a<<endl;
#define all(a) begin(a), end(a)
#define pb(x) push_back(x)
typedef long long ll;
typedef pair<int,int> PII;
const int N=1e5+10,M=2*N;
int t,n,m,ans=0,s=1;
int a[N],dist[110][110];
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++)cin>>a[i];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>dist[i][j];
for(int k = 1; k <= n; k++)
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
for(int i=1;i<m;i++)
{
int x=a[i],y=a[i+1];
ans+=dist[x][y];
}
cout<<ans;
return 0;
}
P3905 道路重建
#include <bits/stdc++.h>
using namespace std;
#define debug(a) cout<<#a<<"="<<a<<endl;
#define all(a) begin(a), end(a)
#define pb(x) push_back(x)
typedef long long ll;
typedef pair<int,int> PII;
const int N=1e5+10,M=2*N;
int t,n,m,ans=0,s=1;
int h[110][110],d[110][110];
void fd() {
for(int k = 1; k <= n; k++)
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
h[i][j] = min(h[i][j], h[i][k] + h[k][j]);
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i==j)h[i][j]=0;
else h[i][j]=0x3f3f3f3f;
}
for(int i=1;i<=m;i++)
{
int x,y;cin>>x>>y;
cin>>d[x][y];
d[y][x]=d[x][y];
h[x][y]=h[y][x]=0;
}
int k;
cin>>k;
for(int i=1;i<=k;i++)
{
int s,e;
cin >> s >> e;
h[s][e]=h[e][s]=d[s][e];
}
fd();
int x,y;
cin>>x>>y;
cout<<h[x][y];
return 0;
}
P2888 [USACO07NOV] Cow Hurdles S
//对于Floyd进行了一点小小的优化
#include<bits/stdc++.h>
using namespace std;
int n,m,t,dis[1000][1000],a,b,c,x,y;
int main(){
cin>>n>>m>>t;
memset(dis,0x3f,sizeof(dis));
for(int i=1;i<=m;i++){
cin>>a>>b>>c;
dis[a][b]=c;
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int s=max(dis[i][k],dis[k][j]);
if(s!=0x3f3f3f3f&&s<dis[i][j]){
dis[i][j]=s;
}
}
}
}
for(int i=1;i<=t;i++){
cin>>x>>y;
if(dis[x][y]==0x3f3f3f3f){
cout<<-1<<endl;
continue;
}
cout<<dis[x][y]<<endl;
}
return 0;
}