hdu 1874 畅通工程续 dijsktra dijkstra+邻接表 优先队列 bellman-ford bellman-ford队列优化(基础题目,一步步优化)

来源:互联网 发布:按键精灵免费网络验证 编辑:程序博客网 时间:2024/05/01 07:12

又是一道最短路基础题目,注意两点就可以了:

1.输入的时候可能会两点之间有多条路,选最短的存起来。

2.判断有没有路径存在,可以判断一下终点到起点的距离是否小于原来初始化的最大值,如果是就输出结果,否则输出-1

代码:

<span style="font-family:Courier New;font-size:18px;"><span style="font-family:Courier New;font-size:18px;">#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<vector>#include<set>#include<string>#include<algorithm>#define MAX 10010000using namespace std;int d[205];int gra[205][205];int visit[205];int n,m,s,t;void dijkstra(){int i,j;for(i=0; i<n; i++)d[i] = MAX;d[s] = 0;memset(visit,0,sizeof(visit));for(i=0; i<n; i++){int x ,y = MAX;for(j=0; j<n; j++){if(!visit[j] && d[j] < y)y = d[x = j];}visit[x] = 1;for(j=0; j<n; j++)if(!visit[j] && d[j]>d[x]+gra[x][j])d[j] = d[x] + gra[x][j];} return ;}int main(){int i,j,a,b,c;while(cin >> n >> m){for(i=0; i<n; i++)for(j=0; j<n; j++)gra[i][j] = MAX;for(i=1; i<=m; i++){cin >> a >> b >> c;if(gra[a][b] > c) gra[a][b] = gra[b][a] = c;}cin >> s >> t;dijkstra();if(d[t] < MAX)cout << d[t] << endl;elsecout << -1 << endl;}return 0;}</span>

vetor:

更新其他点的距离的时候用vetor,可以保证每次都访问的是与它相邻的边,从而节约时间

代码:

<span style="font-family:Courier New;font-size:18px;"><span style="font-family:Courier New;font-size:18px;">#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<vector>#include<set>#include<string>#include<algorithm>#define MAX 10010000using namespace std;int d[205];int gra[205][205];vector<int>v[205]; int visit[205];int n,m,s,t;void dijkstra(){int i,j;for(i=0; i<n; i++)d[i] = MAX;d[s] = 0;memset(visit,0,sizeof(visit));for(i=0; i<n; i++){int x ,y = MAX;for(j=0; j<n; j++){if(!visit[j] && d[j] < y)y = d[x = j];}visit[x] = 1;//for(j=0; j<n; j++)//if(!visit[j] && d[j]>d[x]+gra[x][j])//d[j] = d[x] + gra[x][j];for(j=0; j<v[x].size(); j++)if(!visit[v[x][j]] && d[v[x][j]]>d[x]+gra[x][v[x][j]])d[v[x][j]] = d[x] + gra[x][v[x][j]];} return ;}int main(){int i,j,a,b,c;while(cin >> n >> m){for(i=0; i<205; i++)v[i].clear();for(i=0; i<n; i++)for(j=0; j<n; j++)gra[i][j] = MAX;for(i=1; i<=m; i++){cin >> a >> b >> c;if(gra[a][b] > c) {gra[a][b] = gra[b][a] = c;v[a].push_back(b);v[b].push_back(a);}}cin >> s >> t;dijkstra();if(d[t] < MAX)cout << d[t] << endl;elsecout << -1 << endl;}return 0;}</span></span>
优先队列:

又使用了小白书上介绍的STL里面的优先队列:priority_queue<int>q ,默认的是从大到小排列,从队列中取元素的时候队头都是优先级大的,用q.top()去元素,如果想让它从小到大排列,可以用greater<int>作:"大于"运算符,即priority_queue<int,vector<int>,greater<int> >q,记得最后的两个> >之间加空格,

否则会默认成<<移位运算符,还有两种方法可以重载一下小于运算符,暂时没去研究。。。用c++交的时候greater的使用得加头文件#include<functional> ,否则会编译错误,g++交就没事。pair是专门把另个类型捆绑在一起的,pair<int,int>pii,则优先队列priority_queue<pii,vector<pii>,greater<pii> >q,这道题目必须用两个元素来排队,一个是距离,一个是编号,可以用make_pair(int,int)来组成一个pair类型元素。pair的比较规则是先比较第一维,相等的时候比较第二维。

代码:

<span style="font-family:Courier New;font-size:18px;">#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<vector>#include<set>#include<queue> #include<string>#include<algorithm>#include<utility>#include<functional> #define MAX 10010000using namespace std;int d[205];typedef pair<int,int>p;priority_queue<p, vector<p>, greater<p> >q;int gra[205][205];vector<int>v[205]; int visit[205];int n,m,s,t;void dijkstra(){int i,j;for(i=0; i<n; i++)d[i] = MAX;d[s] = 0;memset(visit,0,sizeof(visit));q.push(make_pair(d[s],s)); while(!q.empty()){p u = q.top();q.pop();int x = u.second;if(visit[x])continue;visit[x] = 1;for(j=0; j<v[x].size(); j++)if(!visit[v[x][j]] && d[v[x][j]]>d[x]+gra[x][v[x][j]]){d[v[x][j]] = d[x] + gra[x][v[x][j]];q.push(make_pair(d[v[x][j]],v[x][j]));}}/*for(i=0; i<n; i++){int x ,y = MAX;for(j=0; j<n; j++){if(!visit[j] && d[j] < y)y = d[x = j];}visit[x] = 1;//for(j=0; j<n; j++)//if(!visit[j] && d[j]>d[x]+gra[x][j])//d[j] = d[x] + gra[x][j];for(j=0; j<v[x].size(); j++)if(!visit[v[x][j]] && d[v[x][j]]>d[x]+gra[x][v[x][j]])d[v[x][j]] = d[x] + gra[x][v[x][j]];} */return ;}int main(){int i,j,a,b,c;while(cin >> n >> m){for(i=0; i<205; i++)v[i].clear();for(i=0; i<n; i++)for(j=0; j<n; j++)gra[i][j] = MAX;for(i=1; i<=m; i++){cin >> a >> b >> c;if(gra[a][b] > c) {gra[a][b] = gra[b][a] = c;v[a].push_back(b);v[b].push_back(a);}}cin >> s >> t;dijkstra();if(d[t] < MAX)cout << d[t] << endl;elsecout << -1 << endl;}return 0;}</span>


bellman-ford算法:

代码:

<span style="font-family:Courier New;font-size:18px;">#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<vector>#include<set>#include<queue> #include<string>#include<algorithm>#include<utility>#include<functional> #define MAX 10010000using namespace std;struct node{int i,j,len;}edge[40005];int d[205];int n,m,s,t;void bellmanford(){int i,k,j;for(i=0; i<n; i++)d[i] = MAX;d[s] = 0;for(i=1; i<=n-1; i++){for(j=1; j<=2*m; j++){int x = edge[j].i,y = edge[j].j;if(d[x] < MAX){d[y] = (d[y] > d[x]+(edge[j].len)) ? (d[x]+(edge[j].len)) : d[y];}}}} int main(){int i,j,a,b,c;while(cin >> n >> m){for(i=1; i<=n*n; i++)edge[i].len = MAX;for(i=1; i<=m; i++){cin >> a >> b >> c;edge[i+m].j = edge[i].i = a;edge[i+m].i = edge[i].j = b;edge[i+m].len = edge[i].len = c;}cin >> s >> t;bellmanford();if(d[t] < MAX)cout << d[t] << endl;elsecout << -1 << endl;}return 0;}</span>

spfa(用队列优化bellmanford),bellmanford每次都是遍历所有的边,其实只需要每次都遍历更新过的边,这样也可以保证不断更新距离:

代码:

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<vector>#include<set>#include<queue> #include<string>#include<algorithm>#include<utility>#include<functional> #define MAX 10010000using namespace std;int d[205];int gra[205][205];vector<int>v[205]; int visit[205];int n,m,s,t;void dijkstra(){int i,j;for(i=0; i<n; i++)d[i] = MAX;d[s] = 0;memset(visit,0,sizeof(visit));queue<int>q; q.push(s); while(!q.empty()){int x = q.front();q.pop();visit[x] = 0;for(j=0; j<v[x].size(); j++)if(d[v[x][j]]>d[x]+gra[x][v[x][j]]){d[v[x][j]] = d[x] + gra[x][v[x][j]];if(!visit[v[x][j]]){q.push(v[x][j]);visit[v[x][j]] = 1;}}}return ;}int main(){int i,j,a,b,c;while(cin >> n >> m){for(i=0; i<205; i++)v[i].clear();for(i=0; i<n; i++)for(j=0; j<n; j++)gra[i][j] = MAX;for(i=1; i<=m; i++){cin >> a >> b >> c;if(gra[a][b] > c) {gra[a][b] = gra[b][a] = c;v[a].push_back(b);v[b].push_back(a);}}cin >> s >> t;dijkstra();if(d[t] < MAX)cout << d[t] << endl;elsecout << -1 << endl;}return 0;}



0 0