关于图论中最短路径的五道题-ACM
来源:互联网 发布:如何评价阿凡达 知乎 编辑:程序博客网 时间:2024/06/06 04:25
ACM队内训练第六周的专题是图论中最短路径问题,今晚终于把五道题目都AC了,下面依次总结一下并奉上代码。
题目列表
NO.1 poj1125 Stockbroker Grapevine
题目给定一个有向图,求解最短路径,要求输出作为源的顶点坐标以及该顶点到达某个顶点的最大权值。数据量100,使用Floyd算法,复杂度为n^3。无特殊处理。
/*最短路径算法-Floyd算法*/#include <iostream>#include<cstring>#include<stdio.h>#include<cstdlib>#include<cmath>#include<string>#include<vector>#include<list>#include<map>#include<queue>#include<stack>#include<algorithm>using namespace std;#define maxn 0x3f3f3f3fstruct Graph{ //邻接矩阵表示法 int arcs[105][105];}g;struct ShortPath{ int a[105][105];}path;void floyd(int n){ for(int i=0 ; i<n ; i++) //初始化 for(int j=0 ; j<n ; j++) path.a[i][j] = g.arcs[i][j]; for(int k=0 ; k<n ; k++) for(int i=0 ; i<n ; i++) for(int j=0 ; j<n ; j++){ if(path.a[i][k]>=maxn || path.a[k][j]>=maxn) continue; if(path.a[i][j] > (path.a[i][k] + path.a[k][j])) path.a[i][j] = path.a[i][k] + path.a[k][j]; }}int main(){ //freopen("in.txt","r",stdin); int n; while(cin>>n && n!=0){ int m,j; memset(g.arcs,maxn,sizeof(g.arcs)); for(int i=0 ; i<n ; i++) g.arcs[i][i]=0; for(int i=0 ; i<n ; i++){ cin>>m; while(m--){ cin>>j; cin>>g.arcs[i][j-1]; } } floyd(n); int shortpath=maxn,pathlen,point=0; for(int i=0 ; i<n ; i++){ bool flag=true; pathlen=0; for(int j=0 ; j<n ; j++){ if(path.a[i][j]>=maxn){ flag=false; break; } pathlen += path.a[i][j]; } if(!flag) continue; if(shortpath>pathlen){ shortpath=pathlen; point=i; } } if(shortpath>=maxn) cout<<"disjoint"<<endl; else{ cout<<point+1<<" "; sort(path.a[point],path.a[point]+n); cout<<path.a[point][n-1]<<endl; } } return 0;}
NO.2 poj3615 Cow Hurdles
题目要求最短路径中任意两点的最大距离,采用Floyd算法,直接把二维数组用作邻接矩阵,WA了两次,原因是输入时需注意从一根柱子跳到另一根柱子是不可逆的,也就是说a[x][y]!=a[y][x]。
#include <iostream>#include<cstring>#include<stdio.h>#include<cstdlib>#include<cmath>#include<string>#include<vector>#include<list>#include<map>#include<queue>#include<stack>#include<algorithm>using namespace std;#define maxn 0x3f3f3f3fint a[305][305];void floyd(int n){ for(int k=1 ; k<=n ; k++) for(int i=1 ; i<=n ; i++) for(int j=1 ; j<=n ; j++) a[i][j] = min(a[i][j],max(a[i][k],a[k][j]));}int main(){ int n,m,t; while(scanf("%d%d%d",&n,&m,&t)!=EOF){ int x,y,z; // memset(a,maxn,sizeof(a)); for(int i=1 ; i<=n ; i++) for(int j=1 ; j<=n ; j++) a[i][j]=maxn; while(m--){ //cin>>x>>y; scanf("%d%d%d",&x,&y,&z); a[x][y]=z; //a[y][x]=a[x][y];错误,需留意 } floyd(n); while(t--){ scanf("%d%d",&x,&y); if(a[x][y]>=maxn) printf("-1\n"); else printf("%d\n",a[x][y]); } } return 0;}
NO.3 poj1847 Tram
题目意思是说有n个点,从A点到其他点,若可达且是该行输入的第一个点则权值为0,若可达且不是第一个点则权值为1,否则不可达。由于数据量不大,使用Floyd算法求解。
#include <iostream>#include<cstring>#include<stdio.h>#include<cstdlib>#include<cmath>#include<string>#include<vector>#include<list>#include<map>#include<queue>#include<stack>#include<algorithm>using namespace std;#define maxn 0x3f3f3f3fint point[105][105];int n,a,b;void floyd(){ for(int q=1 ; q<=n ; q++) for(int i=1 ; i<=n ; i++) for(int j=1 ; j<=n ; j++){ if(point[i][j]>(point[i][q]+point[q][j])) point[i][j] = point[i][q]+point[q][j]; }}int main(){ while(~scanf("%d%d%d",&n,&a,&b)){ int m,k; for(int i=1 ; i<=n ; i++){ //初始化 for(int j=1 ; j<=n ; j++){ if(i==j) point[i][j]=0; else point[i][j]=maxn; } } for(int i=1 ; i<=n ; i++){ scanf("%d",&m); for(int j=0 ; j<m ; j++){ scanf("%d",&k); if(j==0) point[i][k]=0; else point[i][k]=1; } } floyd(); if(point[a][b]>=maxn) cout<<-1<<endl; else cout<<point[a][b]<<endl; } return 0;}
NO.4 poj1502 MPI Maelstrom
无向图求最短路径,无特殊要求,直接使用Dijkstra算法求解,复杂度为n^2。
/*Dijkstra算法-最短路*/#include<iostream>#include<cstring>#include<stdio.h>#include<cstdlib>#include<cmath>#include<string>#include<vector>#include<list>#include<map>#include<queue>#include<stack>#include<algorithm>using namespace std;#define max 0x3f3f3f3fstruct Graph{ //邻接矩阵表示法 int arcs[105][105];}g;int dist[105]; //储存最短路径void init(Graph pg,int dist[],int n){ dist[0] = 0; pg.arcs[0][0] = 1; //若对角线元素为1,则表示该顶点已被使用 for(int i=1 ; i<n ; i++) dist[i] = pg.arcs[0][i];}void dijkstra(Graph g,int dist[],int n){ int mv,minw; init(g,dist,n); //初始化 for(int i=1 ; i<n ; i++){ minw=max; mv=0; for(int j=1 ; j<n ; j++) //选出距离v0最近的顶点 if(g.arcs[j][j]==0 && dist[j]<minw){ mv=j; minw=dist[j]; } if(mv == 0) break; //v0与vi不连通,结束 g.arcs[mv][mv] = 1; for(int j=1 ; j<n ; j++){ if(g.arcs[j][j]==0 && dist[j] >dist[mv]+g.arcs[mv][j]){ dist[j] = dist[mv]+g.arcs[mv][j]; } } }}int main(){ int n; while(cin>>n){ memset(g.arcs,0,sizeof(g.arcs)); string input; for(int i=1 ; i<n ; i++){ for(int j=0 ; j<i ; j++){ cin>>input; if(input=="x"){ g.arcs[i][j]=max; g.arcs[j][i]=max; }else{ g.arcs[i][j]=atoi(input.c_str()); g.arcs[j][i]=atoi(input.c_str()); } } } dijkstra(g,dist,n); sort(dist,dist+n); cout<<dist[n-1]<<endl; } return 0;}
NO.5 poj1860 Currency Exchange
Bellman_Ford算法求解有向带权图是否存在正负环。数组开小导致RE,遍历的时候注意起点,输入的变量较多,顺序容易搞错。
#include <iostream>#include<cstring>#include<stdio.h>#include<cstdlib>#include<cmath>#include<string>#include<vector>#include<list>#include<map>#include<queue>#include<stack>#include<algorithm>using namespace std;struct Edge{ int u,v; double rate,cost;};Edge edge[1005];double dist[5005];double ss;int start,count1;bool Bellman_Ford(int n){ memset(dist,0,sizeof(dist)); dist[start]=ss; bool flag; for(int i=1 ; i<n ; i++){ flag=false; for(int j=0 ; j<count1 ; j++) if(dist[edge[j].v] < (dist[edge[j].u]-edge[j].cost)*edge[j].rate){ dist[edge[j].v] = (dist[edge[j].u]-edge[j].cost)*edge[j].rate; flag = true; } if(!flag) break; } for(int j=0 ; j<count1 ; j++) if(dist[edge[j].v] < (dist[edge[j].u]-edge[j].cost)*edge[j].rate) return true; return false;}int main(){ int n,m; while(cin>>n>>m>>start>>ss){ count1=0; int uu,vv; double p1,p2,p3,p4; while(m--){ cin>>uu>>vv>>p1>>p2>>p3>>p4; edge[count1].u=uu; edge[count1].v=vv; edge[count1].rate=p1; edge[count1].cost=p2; count1++; edge[count1].u=vv; edge[count1].v=uu; edge[count1].rate=p3; edge[count1].cost=p4; count1++; } if(Bellman_Ford(n)) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0;}
结语
图论的题目接触不多,一开始写的代码有些赘余,后来发现后慢慢改正一些。感受最深的一处是:数据量不大的情况下,直接用二维数组表示图的邻接矩阵比较方便。以后做ACM题要有快速建模的意识!
0 0
- 关于图论中最短路径的五道题-ACM
- ACM中的图中关于最短路径的dijistra算法和bellman_ford算法
- 关于ACM的输入输出
- 关于acm的种种
- 关于ACM的输入输出
- 关于ACM的输入输出
- 关于acm的事。
- 关于web的路径
- 关于JAVA的路径
- 关于路径的问题
- 关于JAVA的路径
- 关于路径"/" “./” “../” "/" ""的区别
- 关于ACM的一些资料
- 关于ACM的总结&&前瞻
- 一道关于DP的ACM
- 关于ACM的一个规划
- 关于我的ACM-ICPC
- 关于ACM的一些思考
- Python微博地点签到大数据实战(一)微博API的使用
- dsaf
- Android学习实践:9.多选框CheckBox
- jQuery CSS 操作 - offsetParent() 方法
- Eclipse配置Tomcat服务器
- 关于图论中最短路径的五道题-ACM
- u3d坐标系详解
- hihoCoder1232 Couple Trees LCA倍增算法+二分
- boost笔记
- 字符编码细谈
- UICollectionView的布局
- java正确显示出字母且单词长度大于4的
- View 的事件分发机制
- WordPress搬家数据库问题 error establishing a database connection