答疑:解题遇到问题?分享解题心得?讨论本题请访问:http://t.jobdu.com/thread-7732-1-1.html
分析:自己用的是Dijkstra算法写的,感觉特别好;大致思想也就是找权值最小的边,如果有边相等,则找花费最小的边。
#include <iostream>#include <fstream>using namespace std;struct cost{int d;//距离 int p;// 花费 }dist[1001];struct graph{int n,e; //节点数和边数 }g;int mapd[1001][10001];//存的是边的距离 int mapp[1001][10001]; //存的是边的花费 const int INF = 2100000000; //这里视为权值无穷大 int path[1001];//记录选取的中间节点 void Dijkstra(graph g,int s0);int main(){ifstream in;in.open("1.txt");int n,m;int s0,s1;while(in>>n>>m,n||m)//当且仅当n和m全为false时表达式的值为false,否则为true,{//也就是如果n和m中只要有一个不为0表达式的值就为1,while就一直循环g.n=n;g.e=m;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){mapd[i][j]=INF; mapp[i][j]=INF;} for(int i=1;i<=m;i++){int j,k;in>>j>>k;in>>mapd[j][k]>>mapp[j][k];//无向图,二个方向都要设置权值 mapd[k][j]=mapd[j][k];mapp[k][j]=mapp[j][k];}in>>s0>>s1; Dijkstra(g,s0);cout<<dist[s1].d<<" "<<dist[s1].p<<endl;}return 0; } void Dijkstra(graph g,int s0) { int set[1001];//节点访问的标志 int min1,min2,i,j,u; for(i=1;i<=g.n;i++) { dist[i].d=mapd[s0][i]; dist[i].p=mapp[s0][i]; set[i]=0; if(mapd[s0][i]<INF) path[i]=s0; else path[i]=-1;} set[s0]=1;path[s0]=-1;for(int i=1;i<=g.n;i++){min1=INF;//距离的最小值 min2=INF;//花费的最小值 for(j=1;j<=g.n;j++){if(set[j]==0 && dist[j].d<min1)//选择距离小的边 {u=j;min1=dist[j].d;min2=dist[j].p;}else if(set[j]==0 && dist[j].d==min1 && dist[j].p<min2)//若边的距离相等,选择花费小的边 {u=j;min1=dist[j].d;min2=dist[j].p;}}set[u]=1;//将其加入到最短路径的点集里 for(j=1;j<=g.n;j++){if(set[j]==0 && dist[u].d+mapd[u][j]<dist[j].d){dist[j].d=dist[u].d+mapd[u][j];dist[j].p=dist[u].p+mapp[u][j];path[j]=u;}else if(set[j]==0 && dist[u].d+mapd[u][j]==dist[j].d && dist[u].p+mapp[u][j]<dist[j].p){dist[j].d=dist[u].d+mapd[u][j];dist[j].p=dist[u].p+mapp[u][j];path[j]=u;}}} }
自己又用Floyd写了,但由于这个算法的复杂度为o(n^3),所以提交时间通不过#include <iostream>#include <fstream>using namespace std;int a[1001][1001];int b[1001][1001];const int INF=210000;void Floyd(int n);int main(){ifstream in;in.open("1.txt");int n,m;int s,t; while(in>>n>>m,m||n){for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)b[i][j]=a[i][j]=INF;for(int i=1;i<=m;i++){int j,k;in>>j>>k;in>>a[j][k]>>b[j][k];a[k][j]=a[j][k];b[k][j]=b[j][k];}in>>s>>t;Floyd(n);cout<<a[s][t]<<" "<<b[s][t]<<endl;} return 0;}void Floyd(int n){int i,j,k;for(k=1;k<=n;k++)for(i=1;i<=n;i++)for(j=1;j<=n;j++){if(a[i][j]>a[i][k]+a[k][j]){a[i][j]=a[i][k]+a[k][j];b[i][j]=b[i][k]+b[k][j];}else if(a[i][j]==a[i][k]+a[k][j] && b[i][j]>b[i][k]+b[k][j]){b[i][j]=b[i][k]+b[k][j];}}}
找了一下别人写的#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> using namespace std; int n, m; int map[1010][1010]; bool vi[1010]; int cost[1010][1010]; int dis[1010]; int price[1010]; int s, t; const int INF = 2100000000; void init() { for (int i = 1; i <= n; ++ i) { vi[i] = false; dis[i] = INF; price[i] = INF; for (int j = 1; j <= n; ++ j) { map[i][j] = INF; } } for (int i = 0; i < m; ++ i) { int from, to, d, p; scanf("%d%d%d%d", &from, &to, &d, &p); map[to][from] = map[from][to] = d; cost[to][from] = cost[from][to] = p; } scanf("%d%d", &s, &t); } void dijkstra() { dis[s] = 0; price[s] = 0; for (int k = 0; k < n; ++ k) { int index = -1; int minn = INF; for (int i = 1; i <= n; ++ i) { if (vi[i]==false && dis[i]<minn) { index = i; minn = dis[i]; } } vi[index] = true; for (int j = 1; j <= n; ++ j) { if (dis[j] > dis[index] + map[index][j]) { dis[j] = dis[index] + map[index][j]; price[j] = price[index] + cost[index][j]; } else if (dis[j] == dis[index] + map[index][j]) { price[j] = min(price[j], price[index]+cost[index][j]); } } } } int main() { while (cin >> n >> m, n || m) { init(); dijkstra(); cout << dis[t] << " " << price[t] << endl; } return 0; }