hdu 3790 最短路径问题
最短路径问题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 32689 Accepted Submission(s): 9611
Problem Description
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
Input
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)
(1<n<=1000, 0<m<100000, s != t)
Output
输出 一行有两个数, 最短距离及其花费。
Sample Input
3 2
1 2 5 6
2 3 4 5
1 3
0 0
Sample Output
9 11
Source
思路:此题为最短路径水题,将采用不同算法来进行练习,Floyd运行超时可以理解,第一个算法用cin就超时,hdu是不是对C++有歧视啊?????
- Dijkstra算法:
#include<cstdio> #include<climits> #include<iostream> using namespace std; int len[1005], mon[1005], vis[1005]; int mapp[1005][1005], mapd[1005][1005]; int n, m; void dijkstra(int s) { memset(vis, 0, sizeof(vis)); for (int i = 1; i <= n; i++){ len[i] = mapd[s][i]; mon[i] = mapp[s][i]; } vis[s] = 1; len[s] = mon[s] = 0; for (int i = 1; i < n; i++){ int min = INT_MAX, p = 1; for (int j = 1; j <= n; j++){ if (min > len[j] && vis[j] == 0){ min = len[j]; p = j; } } vis[p] = 1; for (int j = 1; j <= n; j++){ if (len[p] + mapd[p][j] < len[j] && vis[j] == 0){ len[j] = len[p] + mapd[p][j]; mon[j] = mon[p] + mapp[p][j]; } else if (len[p] + mapd[p][j] == len[j] && vis[j] == 0){ if (mon[p] + mapp[p][j] < mon[j]) mon[j] = mon[p] + mapp[p][j]; } } } } int main() { while (cin >> n >> m, n&&m){ for (int i = 0; i <= n; i++) for (int j = 0; j <= n; j++) mapd[i][j] = mapp[i][j] = 999999; for (int i = 0; i < m; i++){ int a, b, d, p; //cin >> a >> b >> d >> p; scanf("%d%d%d%d", &a, &b, &d, &p); if (d < mapd[a][b]) { mapd[a][b] = mapd[b][a] = d; mapp[a][b] = mapp[b][a] = p; } else if (mapd[a][b] == d&&mapp[a][b] > p){ mapp[a][b] = mapp[b][a] = p; } } int s, t; cin >> s >> t; dijkstra(s); cout << len[t] << " " << mon[t] << endl; } return 0; }
- 不知道叫什么名字的算法:
#include<cstdio> #include<vector> #include<cstring> #include<iostream> using namespace std; int len[1005], mon[1005]; struct Node{ int a, b, d, p; }; vector<Node>way; int main() { int n, m; while (cin >> n >> m, n&&m){ way.clear(); //很重要 for (int i = 0; i < m; i++){ Node temp; //cin >> temp.a >> temp.b >> temp.d >> temp.p; scanf("%d%d%d%d", &temp.a, &temp.b, &temp.d, &temp.p); way.push_back(temp); } int s, t; cin >> s >> t; //memset(len, 125, sizeof(len)); //memset(mon, 125, sizeof(mon)); for (int i = 0; i <= n; i++){ len[i] = mon[i] = 999999; } len[s] = 0; mon[s] = 0; int flag = 1; while (flag){ flag = 0; for (int i = 0; i < way.size(); i++){ int a = way[i].a, b = way[i].b, d = way[i].d, p = way[i].p; if (len[a] + d < len[b]){ flag = 1; len[b] = len[a] + d; mon[b] = mon[a] + p; } else if (len[a] + d == len[b] && mon[a] + p < mon[b]){ flag = 1; mon[b] = mon[a] + p; } if (len[b] + d < len[a]){ flag = 1; len[a] = len[b] + d; mon[a] = mon[b] + p; } else if (len[b] + d == len[a] && mon[b] + p < mon[a]){ flag = 1; mon[a] = mon[b] + p; } } } cout << len[t] << " " << mon[t] << endl; } return 0; }
- Floyd算法:
#include<cstdio> #include<vector> #include<cstring> #include<iostream> using namespace std; int mapd[1005][1005], mapp[1005][1005]; int main() { int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++){ mapp[i][j] = 9999; mapd[i][j] = 9999; } for (int i = 0; i < m; i++){ int a, b, d, p; //cin >> a >> b >> d >> p; scanf("%d%d%d%d", &a, &b, &d, &p); mapd[a][b] = mapd[b][a] = d; mapp[a][b] = mapp[b][a] = p; } for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) for (int k = 1; k <= n; k++){ if (mapd[i][k] + mapd[k][j] < mapd[i][j]){ mapd[i][j] = mapd[i][k] + mapd[k][j]; mapp[i][j] = mapp[i][k] + mapp[k][j]; } else if (mapd[i][k] + mapd[k][j] == mapd[i][j]){ if (mapp[i][k] + mapp[k][j] < mapp[i][j]) mapp[i][j] = mapp[i][k] + mapp[k][j]; } } int s, t; while (cin >> s >> t, s&&t){ cout << mapd[s][t] << " " << mapp[s][t] << endl; } return 0; }
今天先到这里,感谢昨天前女友送的一箱三只松鼠;
- bellman-ford算法(虽然没有AC,不知道毛病在哪):
#include<cstdio> #include<cmath> #include<iostream> using namespace std; int n, m; typedef struct Edge{ int a, b, d, p; }Edge; Edge edge[100005]; int len[1005], mon[1005]; bool Bellman_ford(int s) { for (int i = 1; i <= n; i++){ len[i] = 9999999; mon[i] = 9999999; } len[s] = mon[s] = 0; for (int i = 1; i <= n - 1; i++) for (int j = 1; j <= m; j++){ if (len[edge[j].b]>len[edge[j].a] + edge[j].d){ len[edge[j].b] = len[edge[j].a] + edge[j].d; mon[edge[j].b] = mon[edge[j].a] + edge[j].p; } else if (len[edge[j].b] == len[edge[j].a] + edge[j].d){ if (mon[edge[j].b]>len[edge[j].a] + edge[j].p) mon[edge[j].b] = mon[edge[j].a] + edge[j].p; } if (len[edge[j].a]>len[edge[j].b] + edge[j].d){ len[edge[j].a] = len[edge[j].b] + edge[j].d; mon[edge[j].a] = mon[edge[j].b] + edge[j].p; } else if (len[edge[j].a] == len[edge[j].b] + edge[j].d){ if (mon[edge[j].a]>len[edge[j].b] + edge[j].p) mon[edge[j].a] = mon[edge[j].b] + edge[j].p; } } bool flag = true; /* for (int i = 1; i <= m; i++){ if (len[edge[i].b] > len[edge[i].a] + edge[i].d){ flag = false; break; } } */ return flag; } int main() { while (cin >> n >> m, n&&m){ for (int i = 1; i <= m; i++) scanf("%d%d%d%d", &edge[i].a, &edge[i].b, &edge[i].d, &edge[i].p); int s, t; cin >> s >> t; if (Bellman_ford(s)) cout << len[t] << " " << mon[t] << endl; } return 0; }
- SPFA算法(未AC):
#include<cstdio> #include<cmath> #include<queue> #include<vector> #include<iostream> using namespace std; const int MAX = 200002; int n, m; struct Node{ int to; int cost; int mon; Node(int a, int b, int c) :to(a), cost(b), mon(c){} }; vector<Node>vec[MAX]; bool vis[MAX] = { false }; long dis[MAX], mon[MAX]; void spfa(int s) { for (int i = 0; i <= n; i++){ vis[i] = false; dis[i] = INT_MAX; mon[i] = INT_MAX; } dis[s] = mon[s] = 0; queue<int>que; que.push(s); while (!que.empty()){ int p = que.front(); que.pop(); vis[p] = false; for (int i = 0; i < vec[p].size(); i++){ Node no = vec[p][i]; if (dis[no.to]>dis[p] + no.cost){ dis[no.to] = dis[p] + no.cost; mon[no.to] = mon[p] + no.mon; if (!vis[no.to]){ que.push(no.to); vis[no.to] = true; } } else if (dis[no.to] == dis[p] + no.cost){ if (mon[no.to] > mon[p] + no.mon){ mon[no.to] = mon[p] + no.mon; if (!vis[no.to]){ que.push(no.to); vis[no.to] = true; } } } } } } int main() { while (cin >> n >> m, n&&m){ for (int i = 0; i < m; i++){ int a, b, d, p; //cin >> a >> b >> d >> p; scanf("%d%d%d%d", &a, &b, &d, &p); vec[a].push_back(Node(b, d, p)); vec[b].push_back(Node(a, d, p)); } int s, t; cin >> s >> t; spfa(s); cout << dis[t] << " " << mon[t] << endl; } return 0; }
后面两种算法心好累,我要换个水题在试试了,baibaibaibai