渣渣先开个头,给自己在网上找几个大神模板,免得做到题目不会
(自己写是不可能自己写的,自己写是ac不了的)
-----------------------
三种算法:Dijkstra,spfa,bellmanford(Dijkstra加堆优化没学清楚,先不加进来了)
时间复杂度:Dijkstra:O(n²) (没有负权时使用)
spfa:O(V*E) (有负权无负圈,但是能检测负圈)
bellmanford:O(V*E) (有负值,有负圈)
SPFA:
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<queue> using namespace std; #define INF 0x3f3f3f3f #define maxn 1111 #define maxm 111111 struct edge { int to; int cost; int next; }g[maxm]; int head[maxm],tol; int dis[maxn];//所有点到起点的最短距离 int E,V;//顶点数 void init()//初始化 { memset(head,-1,sizeof(head)); tol=0; } void add(int u,int v,int c)//单向边,从u到v,权值为c { g[tol].cost=c; g[tol].to=v; g[tol].next=head[u]; head[u]=tol++; } void spfa(int s)//单源最短路,s是起点 { bool vis[maxn]; memset(vis,false,sizeof(vis)); queue<int>que; for(int i=0;i<=V;i++) dis[i]=INF; dis[s]=0; vis[s]=true; que.push(s); while(!que.empty()) { int u=que.front(); que.pop(); vis[u]=false; for(int i=head[u];i!=-1;i=g[i].next) { int v=g[i].to; int c=g[i].cost; if(dis[v]>dis[u]+c) { dis[v]=dis[u]+c; if(!vis[v]) { vis[v]=true; que.push(v); } } } } } int main() { while(~scanf("%d%d",&E,&V)) { init(); while(E--) { int u,v,c; scanf("%d%d%d",&u,&v,&c); add(u,v,c),add(v,u,c); } spfa(1); printf("%d\n",dis[V]); } return 0; } 原文:https://blog.csdn.net/V5ZSQ/article/details/50418905
Dijkstra:(看不懂时左转复制黏贴:https://www.cnblogs.com/wangyuliang/p/9216511.html)
#include<bits/stdc++.h> using namespace std; const int INF = 0x3F3F3F3F; const int N = 1005; int m, n, st, mp[N][N]; int dis[N], vis[N]; void init() { for (int i=1; i<=n; i++) { for (int j=1; j<=n; j++) { if (i == j) mp[i][j] = 0; else mp[i][j] = INF; } dis[i]=INF; } } void creatgraph() { int t1, t2, t3; for (int i=0; i<m; i++) { scanf("%d%d%d", &t1, &t2, &t3);//两个顶点和权值 if (mp[t1][t2] > t3)//防止重复输入相同节点,但是权值不同 mp[t1][t2] = t3; //mp[t2][t1] = t3; } } void dijkstra(int st) { memset(vis, 0, sizeof(vis)); for (int i=1; i<=n; i++) dis[i] = mp[st][i]; vis[st] = 1; for (int i=1; i<=n-1; i++) { //循环n-1次 /*找出离起点最近的点*/ int minn = INF, k = -1; for (int j=1; j<=n; j++) { if (!vis[j] && dis[j]<minn) { minn = dis[j]; k = j; } } if(k==-1) break; vis[k] = 1; for (int j=1; j<=n; j++) { //松弛操作,找到媒介使得出现新的最短路 if (!vis[j] && dis[k]+mp[k][j] < dis[j]) dis[j] = dis[k] + mp[k][j]; } } } int main() { scanf("%d%d%d", &n, &m, &st); //n个顶点,m条边 init(); //初始化地图 creatgraph(); //建图 dijkstra(st); for(int i=1; i<=n; i++) { if(i==1) printf("%d", dis[i]); else printf(" %d", dis[i]); } }
//摘自https://blog.csdn.net/Scar_Halo/article/details/82825418
BellmanFord:
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #define mem(a,b) memset(a,b,sizeof(a)) #define For(a,b) for(int a=0;a<b;a++) using namespace std; const int maxn = 1e4; const int INF = 0x3f3f3f3f; const int inf = 0x3f; int dis[maxn]; struct edge{ int s,e; ///起点,终点 int w; ///权值 }e[maxn]; int n,m; //n为点,m为边的总数 bool bellman(int a,int n) ///求a->其他点的最短路,n为结点总数.可判负环 { memset(dis,inf,(n+1)<<2); dis[a]=0; For(i,n-1) For(j,m) dis[e[j].e]=min(dis[e[j].e],dis[e[j].s]+e[j].w); ///松弛操作 For(i,m) ///松弛完后还能再松弛即代表有负环 if(dis[e[i].e]>dis[e[i].s]+e[i].w) return true; return false; } int main() { cin>>n>>m; For(i,m) cin>>e[i].s>>e[i].e>>e[i].w; if(bellman(1,n)) cout << "有负环" << endl; else for(int i=1;i<=n;i++){ if(dis[i]!=INF) cout<< dis[i] << endl; else cout <<"INF" << endl; } }
//摘自https://blog.csdn.net/bestsort/article/details/80100039
----------------------------------
(顺带把Floyd的模板贴在这)
Floyd核心代码:
for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(e[i][j]>e[i][k]+e[k][j]) e[i][j]=e[i][k]+e[k][j];
(看不懂左转复制黏贴:https://www.cnblogs.com/wangyuliang/p/9216365.html)