算法笔记--最短路算法
1.单源最短路问题
①Bellman-ford算法:
const int N=1e3+5; const int INF=0x3f3f3f3f; struct edge{ int u,v,cost; }; int d[N]; int V; vector<edge>e; void Bellman_ford(int s) { for(int i=0;i<V;i++)d[i]=INF; d[s]=0; while(true) { bool upd=false; for(int i=0;i<e.size();i++) { if(d[e[i].u]!=INF&&d[e[i].v]>d[e[i].u]+e[i].cost) { upd=true; d[e[i].v]=d[e[i].u]+e[i].cost; } } if(!upd)break; } } bool find_negative_loop() { mem(d,0); for(int i=0;i<V;i++) { for(int j=0;j<e.size();j++) { if(d[e[j].v]>d[e[j].u]+e[j].cost) { d[e[j].v]=d[e[j].u]+e[j].cost; if(i==V-1)return true; } } } return false; }
思路:判断是否存在正权环。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=1e3+5; int n,m,s; double V; struct edge { int u,v; double r,c; }; vector<edge>e; double d[N]; bool Bellman() { for(int i=0;i<=n;i++)d[i]=0; d[s]=V; for(int i=1;i<=n;i++) { bool upd=false; for(int j=0;j<e.size();j++) { if(d[e[j].v]<(d[e[j].u]-e[j].c)*e[j].r) { if(i==n)return true; upd=true; d[e[j].v]=(d[e[j].u]-e[j].c)*e[j].r; } } if(!upd)return false; } return false; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin>>n>>m>>s>>V; int u,v; double r,c,_r,_c; while(m--) { cin>>u>>v>>r>>c>>_r>>_c; e.pb(edge{u,v,r,c}); e.pb(edge{v,u,_r,_c}); } if(Bellman())cout<<"YES"<<endl; else cout<<"NO"<<endl; return 0; }
②Dijkstra算法:
普通版:
const int INF=0x3f3f3f3f; const int N=105; int g[N][N]; int d[N]; bool vis[N]; int n,m; void Dijkstra(int s) { mem(d,INF); mem(vis,false); d[s]=0; while(true) { int v=-1; for(int i=1;i<=n;i++) if(!vis[i]&&(v==-1||d[i]<d[v]))v=i; if(v==-1)break; vis[v]=true; for(int i=1;i<=n;i++) { d[i]=min(d[i],d[v]+g[v][i]); } } }
例题:hdu2544最短路
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define ll long long #define ls rt<<1,l,m #define rs rt<<1|1,m+1,r #define pb push_back #define mem(a,b) memset((a),(b),sizeof(a)) const int INF=0x3f3f3f3f; const int N=105; int g[N][N]; int d[N]; bool vis[N]; int n,m; void Dijkstra(int s) { mem(d,INF); mem(vis,false); d[s]=0; while(true) { int v=-1; for(int i=1;i<=n;i++) if(!vis[i]&&(v==-1||d[i]<d[v]))v=i; if(v==-1)break; vis[v]=true; for(int i=1;i<=n;i++) { d[i]=min(d[i],d[v]+g[v][i]); } } } int main() { while(~scanf("%d%d",&n,&m)&&n&&m) { mem(g,INF); for(int i=0;i<m;i++) { int a,b,c; cin>>a>>b>>c; g[a][b]=c; g[b][a]=c; } Dijkstra(1); printf("%d\n",d[n]); } return 0; }
优先队列优化版:
const int N=1e3+5; const int INF=0x3f3f3f3f; int d[N]; int V; struct edge{ int to,cost; }; vector<edge>g[N]; void dijkstra(int s) { priority_queue<pii,vector<pii>,greater<pii> >q; mem(d,INF); d[s]=0; q.push(mp(0,s)); while(!q.empty()) { pii p=q.top(); q.pop(); int v=p.second; if(d[v]<p.first)continue; for(int i=0;i<g[v].size();i++) { edge e=g[v][i]; if(d[e.to]>d[v]+e.cost) { d[e.to]=d[v]+e.cost; q.push(mp(d[e.to],e.to)); } } } }
例题:hdu2544最短路
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define mem(a,b) memset(a,b,sizeof(a)) #define pii pair<int,int> const int N=1e3+5; const int INF=0x3f3f3f3f; int d[N]; int V; struct edge{ int to,cost; }; vector<edge>g[N]; void dijkstra(int s) { priority_queue<pii,vector<pii>,greater<pii> >q; mem(d,INF); d[s]=0; q.push(mp(0,s)); while(!q.empty()) { pii p=q.top(); q.pop(); int v=p.second; if(d[v]<p.first)continue; for(int i=0;i<g[v].size();i++) { edge e=g[v][i]; if(d[e.to]>d[v]+e.cost) { d[e.to]=d[v]+e.cost; q.push(mp(d[e.to],e.to)); } } } } int main() { ios::sync_with_stdio(false); cin.tie(0); int n,m,a,b,c; while(cin>>n>>m) { if(n==0&&m==0)break; for(int i=0;i<N;i++)g[i].clear(); for(int i=0;i<m;i++) { cin>>a>>b>>c; g[a].pb(edge{b,c}); g[b].pb(edge{a,c}); } dijkstra(1); cout<<d[n]<<endl; } return 0; }
③spfa算法:
bool spfa(int s) { mem(d,INF); mem(c,0); mem(vis,false); d[s]=0; c[s]=1; vis[s]=true; queue<int>q; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=false; for(int i=head[u];~i;i=edge[i].next) { if(d[edge[i].to]>d[u]+edge[i].w) { d[edge[i].to]=d[u]+edge[i].w; if(!vis[edge[i].to]) { vis[edge[i].to]=true; c[edge[i].to]++; q.push(edge[i].to); if(c[edge[i].to]>=n) { return true; } } } } } return false; }
spfa判负环:https://blog.csdn.net/forever_dreams/article/details/81161527
2.任意两点间的最短路问题
①Floyd-Warshall算法
int d[N][N]; int n; void Floyd() { for(int k=1;k<=n;k++) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) d[i][j]=min(d[i][j],d[i][k]+d[k][j]); } } }
例题:hdu2544最短路
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define mem(a,b) memset(a,b,sizeof(a)) #define pii pair<int,int> const int N=1e3+5; const int INF=0x3f3f3f3f; int d[N][N]; int n; void Floyd() { for(int k=1;k<=n;k++) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) d[i][j]=min(d[i][j],d[i][k]+d[k][j]); } } } int main() { ios::sync_with_stdio(false); cin.tie(0); int m,a,b,c; while(cin>>n>>m) { if(n==0&&m==0)break; mem(d,INF); for(int i=1;i<=n;i++)d[i][i]=0; for(int i=0;i<m;i++) { cin>>a>>b>>c; d[a][b]=c; d[b][a]=c; } Floyd(); cout<<d[1][n]<<endl; } return 0; }
3.路径还原:
const int N=1e3+5; const int INF=0x3f3f3f3f; int d[N]; int pre[N]; struct edge { int to,cost; }; vector<edge>g[N]; void dijkstra(int s) { mem(d,INF); mem(pre,-1); priority_queue<pii,vector<pii>,greater<pii> >q; d[s]=0; q.push(mp(0,s)); while(!q.empty()) { pii p=q.top(); q.pop(); int v=p.second; if(d[v]<p.first)continue; for(int i=0;i<g[v].size();i++) { edge e=g[v][i]; if(d[e.to]>d[v]+e.cost) { d[e.to]=d[v]+e.cost; pre[e.to]=v; q.push(mp(d[e.to],e.to)); } } } } vector<int> get_path(int t) { vector<int> path; for(;t!=-1;t=pre[t])path.pb(t); reverse(path.begin(),path.end()); return path; }
例题:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> using namespace std; #define ll long long #define mp make_pair #define pb push_back #define pii pair<int,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=1e3+5; const int INF=0x3f3f3f3f; struct edge { int to,cost; }; int d[N]; vector<edge>g[N]; void dijkstra(int s) { mem(d,INF); d[s]=0; priority_queue<pii,vector<pii>,greater<pii> >q; q.push(mp(0,s)); while(!q.empty()) { pii p=q.top(); q.pop(); int v=p.second; if(d[v]<p.first)continue; for(int i=0;i<g[v].size();i++) { edge e=g[v][i]; if(d[e.to]>d[v]+e.cost) { d[e.to]=d[v]+e.cost; q.push(mp(d[e.to],e.to)); } } } } int main() { ios::sync_with_stdio(false); cin.tie(0); int t,n,a,b,c; while(cin>>t>>n) { for(int i=0;i<=n;i++)g[i].clear(); while(t--) { cin>>a>>b>>c; g[a].pb(edge{b,c}); g[b].pb(edge{a,c}); } dijkstra(n); cout<<d[1]<<endl; } return 0; }
路径最大权值最小路
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<iomanip> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define pii pair<int,int> #define pdi pair<double,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=205; const int INF=0x3f3f3f3f; struct edge { int to; double cost; }; vector<edge>g[N]; bool vis[N]; double d[N]; double x[N],y[N]; void dijkstra(int s) { for(int i=0;i<N;i++)d[i]=INF; mem(vis,false); d[s]=0; priority_queue<pdi,vector<pdi>,greater<pdi> >q; q.push(mp(0,s)); while(!q.empty()) { pii p=q.top(); q.pop(); int v=p.second; if(vis[v])continue; vis[v]=true; for(int i=0;i<g[v].size();i++) { edge e=g[v][i]; if(d[e.to]>max(d[v],e.cost)) { d[e.to]=max(d[v],e.cost); q.push(mp(d[e.to],e.to)); } } } } int main() { ios::sync_with_stdio(false); cin.tie(0); int n; int cnt=0; while(cin>>n&&n) { for(int i=1;i<=n;i++) { g[i].clear(); cin>>x[i]>>y[i]; } for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { double dis=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); g[i].pb(edge{j,dis}); g[j].pb(edge{i,dis}); } } dijkstra(1); cout<<"Scenario #"<<++cnt<<endl; cout<<"Frog Distance = "<<fixed<<setprecision(3)<<d[2]<<endl; cout<<endl; } return 0; }
路径流量(最小权值)最大路
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<iomanip> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define pii pair<int,int> #define pdi pair<double,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=1e3+5; const int INF=0x3f3f3f3f; struct edge { int to,cost; }; vector<edge>g[N]; int d[N]; bool vis[N]; void dijkstra(int s) { mem(vis,false); mem(d,0); priority_queue<pii>q; vis[s]=true; for(int i=0;i<g[1].size();i++) { edge e=g[1][i]; d[e.to]=e.cost; q.push(mp(e.cost,e.to)); } while(!q.empty()) { pii p=q.top(); q.pop(); int v=p.second; if(vis[v])continue; vis[v]=true; for(int i=0;i<g[v].size();i++) { edge e=g[v][i]; if(d[e.to]<min(d[v],e.cost)) { d[e.to]=min(d[v],e.cost); q.push(mp(d[e.to],e.to)); } } } } int main() { ios::sync_with_stdio(false); cin.tie(0); int T,n,m,u,v,cost; cin>>T; for(int i=1;i<=T;i++) { cin>>n>>m; for(int i=0;i<=n;i++)g[i].clear(); while(m--) { cin>>u>>v>>cost; g[u].pb(edge{v,cost}); g[v].pb(edge{u,cost}); } dijkstra(1); cout<<"Scenario #"<<i<<":"<<endl<<d[n]<<endl<<endl; } return 0; }
判负环
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<iomanip> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define pii pair<int,int> #define pdi pair<double,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=555; int d[N]; int n; struct edge { int u,v,cost; }; vector<edge>e; bool Bellman(int s) { mem(d,0); for(int i=1;i<=n;i++) { bool upd=false; for(int j=0;j<e.size();j++) { if(d[e[j].v]>d[e[j].u]+e[j].cost) { if(i==n)return true; d[e[j].v]=d[e[j].u]+e[j].cost; upd=true; } } if(!upd)return false; } return false; } int main() { ios::sync_with_stdio(false); cin.tie(0); int f,u,v,t,m,w; cin>>f; while(f--) { cin>>n>>m>>w; e.clear(); while(m--) { cin>>u>>v>>t; e.pb(edge{u,v,t}); e.pb(edge{v,u,t}); } while(w--) { cin>>u>>v>>t; e.pb(edge{u,v,-t}); } if(Bellman(1))cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }
传递闭包
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define pii pair<int,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=105; bool Mp[N][N]; int main() { ios::sync_with_stdio(false); cin.tie(0); int n,m,u,v; cin>>n>>m; mem(Mp,false); for(int i=0;i<m;i++)cin>>u>>v,Mp[u][v]=true; for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) Mp[i][j]=max(Mp[i][j],Mp[i][k]&&Mp[k][j]); int cnt=0; for(int i=1;i<=n;i++) { int t=0; for(int j=1;j<=n;j++)t+=Mp[i][j]+Mp[j][i]; if(t==n-1)cnt++; } cout<<cnt<<endl; return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define pii pair<int,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=105; const int INF=0x3f3f3f3f; int head[N]; ll d[N]; int cnt; struct edge { int to,w,next; }edge[N*N]; void add_edge(int u,int v,int w) { edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } void dijkstra(int s) { mem(d,INF); priority_queue<pii,vector<pii>,greater<pii> >q; d[s]=0; q.push(mp(0,s)); while(!q.empty()) { pii p=q.top(); q.pop(); int u=p.second; if(d[u]<p.first)continue; for(int i=head[u];~i;i=edge[i].next) { if(d[edge[i].to]>d[u]+edge[i].w) { d[edge[i].to]=d[u]+edge[i].w; q.push(mp(d[edge[i].to],edge[i].to)); } } } } int main() { ios::sync_with_stdio(false); cin.tie(0); int n; string w; cin>>n; cnt=0; mem(head,-1); for(int i=2;i<=n;i++) { for(int j=1;j<i;j++) { cin>>w; int cost=0; if(w=="x")cost=INF; else {for(int i=0;i<w.size();i++)cost=cost*10+w[i]-'0';} add_edge(i,j,cost); add_edge(j,i,cost); } } //cout<<1<<endl; dijkstra(1); ll mx=0; for(int i=1;i<=n;i++)mx=max(mx,d[i]); cout<<mx<<endl; return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define pii pair<int,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=105; const int INF=0x3f3f3f3f; int Mp[N][N]; int main() { ios::sync_with_stdio(false); cin.tie(0); int n; string w; cin>>n; for(int i=2;i<=n;i++) { for(int j=1;j<i;j++) { cin>>w; int cost=0; if(w=="x")cost=INF; else {for(int i=0;i<w.size();i++)cost=cost*10+w[i]-'0';} Mp[i][j]=cost; Mp[j][i]=cost; } } int mx=0; for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) Mp[i][j]=min(Mp[i][k]+Mp[k][j],Mp[i][j]); for(int i=2;i<=n;i++)mx=max(mx,Mp[1][i]); cout<<mx<<endl; return 0; }
判断是否存在正权环,bellman有点慢,好像spfa快一点
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<map> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=50; struct edge { int u,v; double w; }; double d[N]; int n; vector<edge>e; map<string,int>mp; bool Bellman() { for(int i=1;i<=n;i++)d[i]=0; d[1]=1; for(int i=1;i<=n;i++) { bool upd=false; for(int j=0;j<e.size();j++) { if(d[e[j].v]<d[e[j].u]*e[j].w) { if(i==n)return true; upd=true; d[e[j].v]=d[e[j].u]*e[j].w; } } if(!upd)return false; } return false; } int main() { ios::sync_with_stdio(false); cin.tie(0); string s,t; int m; double w; int cnt=0; while(cin>>n&&n) { mp.clear(); e.clear(); for(int i=1;i<=n;i++)cin>>s,mp[s]=i; cin>>m; for(int i=1;i<=m;i++) { cin>>s>>w>>t; e.pb(edge{mp[s],mp[t],w}); } if(Bellman())cout<<"Case "<<++cnt<<": Yes"<<endl; else cout<<"Case "<<++cnt<<": No"<<endl; } return 0; }
又做到一题关闭同步失败的,一直TLE,哭唧唧/(ㄒoㄒ)/~~
求每个点到1的最短路,把图反向,求1的最短路就可以了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<map> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define pii pair<int,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=1e6+5; const int INF=0x3f3f3f3f; int d[N]; int head[N]; int u[N],v[N],w[N]; int cnt,p; struct edge { int to,w,next; }edge[N]; void add_edge(int u,int v,int w) { edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } void dijkstra(int s) { priority_queue<pii,vector<pii>,greater<pii> >q; for(int i=1;i<=p;i++)d[i]=INF; d[s]=0; q.push(mp(0,s)); while(!q.empty()) { pii p=q.top(); q.pop(); int u=p.second; if(d[u]<p.first)continue; for(int i=head[u];~i;i=edge[i].next) { if(d[edge[i].to]>p.first+edge[i].w) { d[edge[i].to]=p.first+edge[i].w; q.push(mp(d[edge[i].to],edge[i].to)); } } } } int main() { int T,q; scanf("%d",&T); while(T--) { scanf("%d%d",&p,&q); cnt=0; for(int i=1;i<=p;i++)head[i]=-1; for(int i=1;i<=q;i++) { scanf("%d%d%d",&u[i],&v[i],&w[i]); add_edge(u[i],v[i],w[i]); } ll ans=0; dijkstra(1); for(int i=2;i<=p;i++)ans+=d[i]; cnt=0; for(int i=1;i<=p;i++)head[i]=-1; for(int i=1;i<=q;i++) add_edge(v[i],u[i],w[i]); dijkstra(1); for(int i=2;i<=p;i++)ans+=d[i]; printf("%lld\n",ans); } return 0; }
建好边,跑一遍最短路
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define ll long long #define pb push_back #define pii pair<int,int> #define pdi pair<double,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=205; const int INF=0x3f3f3f3f; struct node { double x,y; }a[N]; double mp[N][N]; double d[N]; int cnt; void dijkstra(int s) { priority_queue<pdi,vector<pdi>,greater<pdi> >q; for(int i=0;i<cnt;i++)d[i]=INF; d[s]=0; q.push(pdi(0,s)); while(!q.empty()) { pdi p=q.top(); q.pop(); if(d[p.second]<p.first)continue; for(int i=0;i<cnt;i++) { if(d[i]>d[p.second]+mp[p.second][i]) { d[i]=d[p.second]+mp[p.second][i]; q.push(pdi(d[i],i)); } } } } int main() { ios::sync_with_stdio(false); cin.tie(0); double sx,sy,ex,ey; double x,y; //freopen("in.txt","r",stdin); cin>>sx>>sy>>ex>>ey; double prex=-1; double prey=-1; cnt=0; a[cnt].x=sx,a[cnt++].y=sy; while(cin>>x>>y) { if(x!=-1)a[cnt].x=x,a[cnt].y=y; if(prex!=-1&&x!=-1) { double t=sqrt((a[cnt].x-a[cnt-1].x)*(a[cnt].x-a[cnt-1].x)+(a[cnt].y-a[cnt-1].y)*(a[cnt].y-a[cnt-1].y))/40000; mp[cnt][cnt-1]=t; mp[cnt-1][cnt]=t; } if(x!=-1)cnt++; prex=x; prey=y; } a[cnt].x=ex; a[cnt++].y=ey; for(int i=0;i<cnt;i++) { for(int j=0;j<cnt;j++) { if(mp[i][j]>0)mp[i][j]=min(sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y))/10000,mp[i][j]); else mp[i][j]=sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y))/10000; } } dijkstra(0); cout<<(int)(d[cnt-1]*60+0.5)<<endl; //fclose(stdin); return 0; }
枚举能跑的点上下界
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define pii pair<int,int> #define pdi pair<double,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=105; const int INF=0x3f3f3f3f; int n,m; struct edge { int to,w,next; }edge[N*N]; int head[N]; int level[N]; int d[N]; int x[N]; int v[N][N]; int t[N][N]; int p[N]; int cnt=0; void add_edge(int u,int v,int w) { edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } void dijkstra(int s,int l,int r) { priority_queue<pii,vector<pii>,greater<pii> >q; mem(d,INF); d[s]=0; q.push(mp(0,s)); while(!q.empty()) { pii p=q.top(); q.pop(); if(d[p.second]<p.first)continue; for(int i=head[p.second];~i;i=edge[i].next) { if(l<=level[edge[i].to]&&level[edge[i].to]<=r&&d[edge[i].to]>d[p.second]+edge[i].w) { d[edge[i].to]=d[p.second]+edge[i].w; q.push(mp(d[edge[i].to],edge[i].to)); } } } } int main() { ios::sync_with_stdio(false); cin.tie(0); cin>>m>>n; for(int i=1;i<=n;i++) { cin>>p[i]>>level[i]>>x[i]; for(int j=0;j<x[i];j++) { cin>>t[i][j]>>v[i][j]; } } mem(head,-1); cnt=0; for(int i=1;i<=n;i++) { for(int j=0;j<x[i];j++) { add_edge(i,t[i][j],v[i][j]); } } int ans=p[1]; for(int l=level[1]-m;l<=level[1];l++) { dijkstra(1,l,l+m); for(int i=2;i<=n;i++)ans=min(ans,d[i]+p[i]); } cout<<ans<<endl; return 0; }
水水的一道最短路,把转动次数看成路径权值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define pii pair<int,int> #define pdi pair<double,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=105; const int INF=0x3f3f3f3f; int head[N]; int d[N]; int cnt; struct edge { int to,w,next; }edge[N*N]; void add_edge(int u,int v,int w) { edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } void dijkstra(int s) { priority_queue<pii,vector<pii>,greater<pii> >q; mem(d,INF); d[s]=0; q.push(mp(0,s)); while(!q.empty()) { pii p=q.top(); q.pop(); if(d[p.second]<p.first)continue; for(int i=head[p.second];~i;i=edge[i].next) { if(d[edge[i].to]>d[p.second]+edge[i].w) { d[edge[i].to]=d[p.second]+edge[i].w; q.push(mp(d[edge[i].to],edge[i].to)); } } } } int main() { ios::sync_with_stdio(false); cin.tie(0); int n,a,b,t,m; cin>>n>>a>>b; cnt=0; mem(head,-1); for(int i=1;i<=n;i++) { cin>>m; if(m) { m--; cin>>t; add_edge(i,t,0); } while(m--) { cin>>t; add_edge(i,t,1); } } dijkstra(a); if(d[b]!=INF)cout<<d[b]<<endl; else cout<<-1<<endl; return 0; }
不会spfa,看来要去学了,用dijkstra剪了一下枝,水过数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define pii pair<int,int> #define pdi pair<double,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=205; const int INF=0x3f3f3f3f; int d[N]; int a[N]; int head[N]; int cnt,n; struct edge { int to,w,next; }edge[N*N]; void add_edge(int u,int v,int w) { edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } void dijkstra(int s) { priority_queue<pii,vector<pii>,greater<pii> >q; mem(d,INF); d[s]=0; q.push(mp(0,s)); while(!q.empty()) { pii p=q.top(); q.pop(); if(d[p.second]<p.first)continue; for(int i=head[p.second];~i;i=edge[i].next) { if(d[edge[i].to]>d[p.second]+edge[i].w) { d[edge[i].to]=d[p.second]+edge[i].w; if(d[edge[i].to]>-10000)q.push(mp(d[edge[i].to],edge[i].to)); } } } } bool bellman() { mem(d,0); for(int i=1;i<=n;i++) { bool upd=false; for(int j=0;j<cnt;j++) { } if(!upd)return false; } return false; } int main() { ios::sync_with_stdio(false); cin.tie(0); int T,m,q,cs=0,u,v,t; cin>>T; while(T--) { cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; cnt=0; mem(head,-1); cin>>m; while(m--)cin>>u>>v,add_edge(u,v,pow(a[v]-a[u],3)); dijkstra(1); cout<<"Case "<<++cs<<":"<<endl; cin>>q; while(q--) { cin>>t; if(d[t]!=INF&&d[t]>=3)cout<<d[t]<<endl; else cout<<"?"<<endl; } } return 0; }
没有点的楼层之间不能建边,而且只能将同一层的点和所在楼层连单向边,不然同一层的点之间可以免费跑,wa到死
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define pii pair<int,int> #define pdi pair<double,int> #define pli pair<ll,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=1e5+5; const ll INF=0x3f3f3f3f3f3f3f3f; int head[2*N]; bool vis[N]; ll d[2*N]; int l[N]; int cnt; int n,c; struct edge { int to,w,next; }edge[10*N]; void add_edge(int u,int v,int w) { edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } void dijkstra(int s) { priority_queue<pli,vector<pli>,greater<pli> >q; mem(d,INF); d[s]=0; q.push(mp(0,s)); while(!q.empty()) { pli p=q.top(); q.pop(); if(d[p.second]<p.first)continue; for(int i=head[p.second];~i;i=edge[i].next) { if(d[edge[i].to]>d[p.second]+edge[i].w) { d[edge[i].to]=d[p.second]+edge[i].w; q.push(mp(d[edge[i].to],edge[i].to)); } } } } int main() { int T,m,t,u,v,w,cs=0; scanf("%d",&T); while(T--) { cnt=0; mem(head,-1); mem(vis,false); scanf("%d%d%d",&n,&m,&c); for(int i=1;i<=n;i++)scanf("%d",&l[i]),vis[l[i]]=true; while(m--)scanf("%d%d%d",&u,&v,&w),add_edge(u,v,w),add_edge(v,u,w); for(int i=1;i<n;i++)if(vis[i]&&vis[i+1])add_edge(n+i,n+i+1,c),add_edge(n+i+1,n+i,c); for(int i=1;i<=n;i++) { add_edge(i,l[i]+n,0); if(l[i]>1)add_edge(i,l[i]-1+n,c),add_edge(l[i]-1+n,i,c); if(l[i]<n)add_edge(i,l[i]+1+n,c),add_edge(l[i]+1+n,i,c); } dijkstra(1); printf("Case #%d: ",++cs); if(d[n]!=INF)printf("%lld\n",d[n]); else printf("-1\n"); } return 0; }
原来spfa这么简单
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=1e3+5; const int INF=0x3f3f3f3f; int d[N]; int head[N]; bool vis[N]; int c[N]; int n; int cnt; struct edge { int to,w,next; }edge[N*N]; void add_edge(int u,int v,int w) { edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } bool spfa(int s) { mem(d,INF); mem(c,0); mem(vis,false); d[s]=0; c[s]=1; vis[s]=true; queue<int>q; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=false; for(int i=head[u];~i;i=edge[i].next) { if(d[edge[i].to]>d[u]+edge[i].w) { d[edge[i].to]=d[u]+edge[i].w; if(!vis[edge[i].to]) { vis[edge[i].to]=true; c[edge[i].to]++; q.push(edge[i].to); if(c[edge[i].to]>=n) { return true; } } } } } return false; } int main() { ios::sync_with_stdio(false); cin.tie(0); int L,D,a,b,c; cin>>n>>L>>D; mem(head,-1); cnt=0; while(L--) { cin>>a>>b>>c; add_edge(a,b,c); } while(D--) { cin>>a>>b>>c; add_edge(b,a,-c); } if(spfa(1))cout<<-1<<endl; else { if(d[n]==INF)cout<<-2<<endl; else cout<<d[n]<<endl; } return 0; }
两种情况,一种最短路,一种是从1和n分别出发的环(不包括自环)
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=305; const int INF=0x3f3f3f; int cost[N][N]; int d[N]; int c[N]; bool vis[N]; int n; bool spfa(int s) { mem(vis,false); mem(c,0); mem(d,0); queue<int>q; for(int i=1;i<=n;i++) { if(i==s)d[s]=INF,vis[s]=false; else d[i]=cost[s][i],q.push(i),vis[i]=true,c[i]=1; } while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=false; for(int i=1;i<=n;i++) { if(d[i]>d[u]+cost[u][i]) { d[i]=d[u]+cost[u][i]; if(!vis[i]) { vis[i]=true; q.push(i); c[i]++; if(c[i]>=n)return true; } } } } return false; } int main() { ios::sync_with_stdio(false); cin.tie(0); while(cin>>n) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>cost[i][j]; spfa(1); int ans=d[n]; int loop1=d[1]; spfa(n); int loop2=d[n]; cout<<min(ans,loop1+loop2)<<endl; } return 0; }