【训练题】单源最优路径 SPFA(队列优化)算法
2016-07-16 16:23
429 查看
【问题描述】
给出N个顶点,M条无向带权边的连通图,和一个出发点(源点)S:请编程计算:
问1、S到其他点的所有路径中,需要经过的最小边最大的那条路径(最小边最大);
问2、S到其他点的所有路径中,需要经过的最大边最小的那条路径(最大边最小);
【输入格式】
第一行:N(N<=50,000),M(M<=100,000),为图的顶点数目和边的数目。
接下来m行,每行三个整数x,y,t,为一条边关联的两个顶点和边的权值。
最后一行一个整数S。
【输出格式】
共N-1行,每行2个整数,第i行的两个整数分别表示从S到顶点i(i!=s)的最小边的最大值,最大边的最小值。
【输入样例】
【输出样例】
【数据范围】
N<=50,000
M<=100,000
思路:
方法一:最优生成树算法
先生成最大生成树(无根树),然后将s定为这棵树的根,那么在树上,任意一点到s的路径上经过的最大边就是“s到该点的最小边的最大值”。
同理,用最小生成树,可以计算“s到该点的最大边的最小值”。
方法二:SPFA算法(最近在学最优路径,因此用该法完成)
第(1)问中用dist[i]表示s到i的所有路径中,最小边最大的那条路径中的最小边的权值。
第(2)问中用dist[i]表示s到i的所有路径中,最大边最小的那条路径中的最大边的权值。
给出N个顶点,M条无向带权边的连通图,和一个出发点(源点)S:请编程计算:
问1、S到其他点的所有路径中,需要经过的最小边最大的那条路径(最小边最大);
问2、S到其他点的所有路径中,需要经过的最大边最小的那条路径(最大边最小);
【输入格式】
第一行:N(N<=50,000),M(M<=100,000),为图的顶点数目和边的数目。
接下来m行,每行三个整数x,y,t,为一条边关联的两个顶点和边的权值。
最后一行一个整数S。
【输出格式】
共N-1行,每行2个整数,第i行的两个整数分别表示从S到顶点i(i!=s)的最小边的最大值,最大边的最小值。
【输入样例】
6 10 1 2 4 1 3 8 2 3 3 2 4 4 2 5 6 3 4 2 3 5 2 4 5 4 4 6 9 5 6 4 1
【输出样例】
4 4 8 4 4 4 4 4 4 4
【数据范围】
N<=50,000
M<=100,000
思路:
方法一:最优生成树算法
先生成最大生成树(无根树),然后将s定为这棵树的根,那么在树上,任意一点到s的路径上经过的最大边就是“s到该点的最小边的最大值”。
同理,用最小生成树,可以计算“s到该点的最大边的最小值”。
方法二:SPFA算法(最近在学最优路径,因此用该法完成)
第(1)问中用dist[i]表示s到i的所有路径中,最小边最大的那条路径中的最小边的权值。
第(2)问中用dist[i]表示s到i的所有路径中,最大边最小的那条路径中的最大边的权值。
/* Name: SPFA Copyright: Twitter & Instagram @stevebieberjr Author: @stevebieberjr Date: 16-07-16 16:42 */ #include<cstdio> #include<vector> #include<cstring> #include<queue> #include<algorithm> #define maxn 50005 #define inf 1000000000 using namespace std; //dist[i]:s到i的所有路径中,最小边最大的那条路径中的最小边的权值 //dist1[i]:s到i的所有路径中,最大边最小的那条路径中的最大边的权值 int n,m,s,dist[maxn],dist1[maxn]; vector<int>g[maxn],w[maxn]; bool inq[maxn]; void SPFA(int s,int *d) { queue<int>q; for(int i=1;i<=n;i++) { d[i]=-inf; //求最小边最大,将初值赋为-inf } memset(inq,0,sizeof(inq)); q.push(s); //s入队列 inq[s]=1; d[s]=inf; //最开始认为s不能到s,所以最小边的最大值为inf while(!q.empty()) { int i=q.front(); q.pop(); inq[i]=0; for(int k=0;k<g[i].size();k++) { int j=g[i][k],c=w[i][k]; int tmp=min(c,d[i]); //tmp为s->j的路径上的最小边 if(tmp>d[j]) //最小边取最大值 { d[j]=tmp; if(inq[j]) continue; q.push(j); inq[j]=1; } } } } void SPFA1(int s,int *d) //与第(1)问相反 { queue<int>q; for(int i=1;i<=n;i++) { d[i]=inf; } memset(inq,0,sizeof(inq)); q.push(s); inq[s]=1; d[s]=-inf; while(!q.empty()) { int i=q.front(); q.pop(); inq[i]=0; for(int k=0;k<g[i].size();k++) { int j=g[i][k],c=w[i][k]; int tmp=max(c,d[i]); if(tmp<d[j]) { d[j]=tmp; if(inq[j]) continue; q.push(j); inq[j]=1; } } } } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); scanf("%d%d",&n,&m); int x,y,t; for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&t); g[x].push_back(y); g[y].push_back(x); w[x].push_back(t); w[y].push_back(t); } //建立图的存储结构 scanf("%d",&s); SPFA(s,dist); SPFA1(s,dist1); for(int i=1;i<=n;i++) { if(i!=s) printf("%d %d\n",dist[i],dist1[i]); } return 0; }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- MySQL 优化
- 肯特·贝克:改变人生的代码整理魔法
- 你应该学习哪种编程语言?
- c++ primer 第五版 笔记前言
- [转]我们需要一种其他人能使用的编程语言
- share_ptr的几个注意点
- 书评:《算法之美( Algorithms to Live By )》
- Google排名优化的几个影响因素
- DB2编程序技巧(1)
- DB2编程序技巧 (四)
- 女人VS编程_国庆快乐
- DB2编程序技巧 (六)
- DB2编程序技巧 (三)
- DB2编程序技巧 (九)
- DB2编程序技巧 (七)
- DB2编程序小小技巧
- DB2编程序技巧 (五)
- 动易2006序列号破解算法公布