三解<单源最短路径模板题>

来源:互联网 发布:java文件命名 编辑:程序博客网 时间:2024/06/06 03:35

单源最短路径模板题,题目见https://www.luogu.org/problem/show?pid=3371
一.Bellman-ford算法

#include<iostream>#include<climits>#include<vector>#include<queue>using namespace std;int n,m,s;long long map[505][505];long long dis[505][505];int u[500001],v[500001],w[500001];long long d[10001];int main(){    cin>>n>>m>>s;    for(int i=1;i<=m;i++){        cin>>u[i]>>v[i]>>w[i];            }    for(int i=1;i<=n;i++){        d[i] = 2147483647;    }    d[s] = 0;    int flag ;    for(int k=1; k<= n-1; k++){        flag = 0;        for(int i = 1; i<= m; i++){            if(d[u[i]] + w[i] < d[v[i]]){                flag = 1;                d[v[i]] = d[u[i]] + w[i];            }            }            if(flag ==0)            break;    }       for(int i=1;i<=n;i++){        cout<<d[i]<<" ";    }    return 0;}

二.SPFA算法

#include<iostream>#include<vector>#include<queue>#include<cstring>using namespace std;const int maxn = 10005;int n,m,s;vector<int> v1[maxn];vector<int> v2[maxn];bool isQueue[maxn];int d[maxn];void bfs(int start){    d[start] = 0;    queue<int> q;    q.push(start);    isQueue[start] = true;    while(!q.empty()){        int u = q.front();            q.pop();        isQueue[u] = false;            for(int j = 0 ;j< v1[u].size();j++){            int v = v1[u][j];            int len = v2[u][j];            if(d[u] + len < d[v]){                d[v] = d[u] + len;                if(!isQueue[v]){                    q.push(v);                    isQueue[v] = true;                }            }        }            }}int main(){    cin >> n >> m >> s;    for(int i = 1; i<= m; i++){        int x,y,t;        cin >> x >> y >> t;        v1[x].push_back(y);        v2[x].push_back(t);    }            for(int i=1;i<=n;i++){        d[i] = 2147483647;    }    bfs(s);    for(int i = 1; i<= n ;i++){        cout << d[i] << " ";    }    return 0;}

三.堆优化Dijkstra算法

/* priority_queue<Type, Container, Functional>如果我们把后面俩个参数缺省的话,优先队列就是大顶堆,队头元素最大。如果要用到小顶堆,则一般要把模板的三个参数都带进去。STL里面定义了一个仿函数 greater<>,对于基本类型可以用这个仿函数声明小顶,priority_queue<int, vector<int>, greater<int> >q;对于自定义类型,则必须自己重载 perator< 或者自己写仿函数,自定义类型重载 operator< 后,声明对象时就可以只带一个模板参数。一点要注意的是priority_queue中的三个参数,后两个可以省去,因为有默认参数,不过如果,有第三个参数的话,必定要写第二个参数。*/#include<iostream>#include<vector>#include<queue>#include<cstring>using namespace std;const int maxn = 10005;int n,m,s;vector<int> v1[maxn];vector<int> v2[maxn];bool isFinish[maxn];int d[maxn];struct node{    int d,no;    //d最短路,no编号     //重载运算符 ,让优先队列以小根堆呈现     friend bool operator < (node a,node b){        return a.d > b.d;    }};void dijkstra(int start){    d[start] = 0;    priority_queue< node > q;  //优先队列,小根堆     node st ;    st.d = 0; st.no = start;    q.push(st);    while(!q.empty()){        node t = q.top();        //因为是优先队列,取队列首部时便是当前最短的。         q.pop();        int u = t.no ;        if(isFinish[u]) continue;  //是否已经在最短路解集里了。         isFinish[u] = true;                 for(int i = 0 ;i<v1[u].size(); i++)      //以队首为起点,寻找可松弛的点,入队列。         {            int v = v1[u][i];            int wv = v2[u][i];            if(d[v] > d[u] + wv)     //可松弛时             {                d[v] = d[u] + wv;                node temp ;                temp.d = d[v];                temp.no = v;                q.push(temp);            }        }    }    }int main(){    cin >> n >> m >> s;    for(int i = 1; i<= m; i++){        int x,y,t;        cin >> x >> y >> t;        v1[x].push_back(y);        v2[x].push_back(t);    }            for(int i = 1; i<= n; i++)           d[i] = 2147483647;    dijkstra(s);    for(int i = 1; i<= n ;i++){        cout << d[i] << " ";    }    return 0;}
原创粉丝点击