PAT A1030 Travel Plan
Sample Input:
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
Sample Output:
0 2 3 3 40
word | meaning |
---|---|
destination | n. 目的地, 终点 |
-
思路1:
同PAT A1003,Dijkstra() -
code1:
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 510;
const int INF = 0xfffffff;
int G[maxn][maxn];
int d[maxn];
int flag[maxn] = {false};
int pre[maxn]; //只存放最优路径
int N, M, S, E;
int cost[maxn][maxn];
int dcost[maxn][maxn];
void Dijkstra(int s){
fill(d, d+maxn, INF);
fill(dcost[0], dcost[0]+maxn*maxn, 0);
d[s] = 0;
for(int i = 0; i < N; ++i){
int mid = -1, MIN = INF;
for(int j = 0; j < N; ++j){
if(flag[j] == false && d[j] < MIN){
mid = j;
MIN = d[j];
}
}
if(mid == -1) return;
flag[mid] = true;
for(int k = 0; k < N; ++k){
if(flag[k] == false && G[mid][k] != INF){
if(G[mid][k] + d[mid] < d[k]){
d[k] = G[mid][k] + d[mid];
dcost[s][k] = dcost[s][mid] + cost[mid][k];
pre[k] = mid;
}else if(G[mid][k] + d[mid] == d[k]){
if(dcost[s][k] > dcost[s][mid] + cost[mid][k]){
d[k] = G[mid][k] + d[mid];
dcost[s][k] = dcost[s][mid] + cost[mid][k];
pre[k] = mid;
}
}
}
}
}
}
int main(){
scanf("%d %d %d %d", &N, &M, &S, &E);
fill(G[0], G[0]+maxn*maxn,INF);
int c1, c2, dis, cos;
for(int i = 0; i < M; ++i){
scanf("%d %d %d %d", &c1, &c2, &dis, &cos);
G[c1][c2] = dis;
G[c2][c1] = dis;
cost[c1][c2] = cos;
cost[c2][c1] = cos;
}
Dijkstra(S);
int e = E;
vector<int> res;
while(e != S){
res.push_back(e);
e = pre[e];
}
res.push_back(S);
for(int i = res.size()-1; 0 <= i; --i)
printf("%d ", res[i]);
printf("%d ", d[E]);
printf("%d", dcost[S][E]);
return 0;
}
- T2 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1100, INF = 0x3fffffff;
int G_len[maxn][maxn], G_cost[maxn][maxn], d[maxn], dc[maxn], pre[maxn];
bool vis[maxn];
void Dijkstra(int start, int destination, int n){
fill(d, d + maxn, INF);
fill(dc, dc + maxn, INF);
memset(vis, false, sizeof(vis));
for(int i = 0; i < n; ++i) pre[i] = i;
d[start] = 0;
dc[start] = 0;
for(int i = 0; i < n; ++i){
int now = -1, Min = INF;
for(int j = 0; j < n; ++j){
if(vis[j] == false && d[j] < Min){
Min = d[j];
now = j;
}
}
if(now == -1 || now == destination) return;
vis[now] = true;
for(int j = 0; j < n; ++j){
if(vis[j] == false && G_len[now][j] != INF){
if(d[now] + G_len[now][j] < d[j]){
d[j] = d[now] + G_len[now][j];
dc[j] = dc[now] + G_cost[now][j];
pre[j] = now;
}else if(d[now] + G_len[now][j] == d[j] && dc[now] + G_cost[now][j] < dc[j]){
dc[j] = dc[now] + G_cost[now][j];
pre[j] = now;
}
}
}
}
}
void DFS(int id, int start){
if(id == start){
printf("%d ", id);
return;
}
DFS(pre[id], start);
printf("%d ", id);
}
int main(){
int n, m, s, e;
scanf("%d %d %d %d", &n, &m, &s, &e);
fill(G_len[0], G_len[0] + maxn * maxn, INF);
fill(G_cost[0], G_cost[0] + maxn * maxn, INF);
for(int i = 0; i < m; ++i){
int c1, c2;
scanf("%d %d", &c1, &c2);
scanf("%d %d", &G_len[c1][c2], &G_cost[c1][c2]);
G_len[c2][c1] = G_len[c1][c2];
G_cost[c2][c1] = G_cost[c1][c2];
}
Dijkstra(s, e, n);
DFS(e, s);
printf("%d %d", d[e], dc[e]);
return 0;
}
- T3 code: 堆优化
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010, INF = 0x3fffffff;
int G[maxn][maxn], cost[maxn][maxn], d[maxn], dc[maxn];
bool vis[maxn];
struct node
{
int id, d;
bool operator < (const node & tmp) const { return d > tmp.d; }
};
int pre[maxn];
void Dijkstra(int s, int dest, int n)
{
fill(d, d + n, INF);
fill(dc, dc + n, INF);
d[s] = 0;
dc[s] = 0;
priority_queue<node> pq;
pq.push(node{s, 0});
while(!pq.empty())
{
node now = pq.top();
pq.pop();
if(now.id == dest) return;
if(vis[now.id]) continue;
vis[now.id] = true;
for(int i = 0; i < n; ++i)
{
if(vis[i] == false && G[now.id][i] != 0)
{
if(now.d + G[now.id][i] < d[i])
{
d[i] = now.d + G[now.id][i];
dc[i] = dc[now.id] + cost[now.id][i];
pre[i] = now.id;
pq.push({i, d[i]});
}else if(now.d + G[now.id][i] == d[i])
{
if(dc[now.id] + cost[now.id][i] < dc[i])
{
dc[i] = dc[now.id] + cost[now.id][i];
pre[i] = now.id;
pq.push({i, d[i]});
}
}
}
}
}
}
void PrintPath(int id, int s)
{
if(id == s)
{
printf("%d", id);
return;
}
PrintPath(pre[id], s);
printf(" %d", id);
}
int main()
{
int nc, m, s, e;
scanf("%d %d %d %d", &nc, &m, &s, &e);
for(int i = 0; i < m; ++i)
{
int c1, c2, dis, cos;
scanf("%d %d %d %d", &c1, &c2, &dis, &cos);
G[c1][c2] = G[c2][c1] = dis;
cost[c1][c2] = cost[c2][c1] = cos;
}
Dijkstra(s, e, nc);
PrintPath(e, s);
printf(" %d %d", d[e], dc[e]);
return 0;
}
- TIPS:
dcost[]
的意义是,起点s到其他各点的最大花费,是一维的,故不需要二维dcost[][]
,只用dcost[]
表示就可以
- 思路2:
Dijkstra()+DFS() - code2:
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 510;
const int INF = 0xfffffff;
int G[maxn][maxn];
int d[maxn];
int flag[maxn] = {false};
vector<int> pre[maxn];
int N, M, S, E;
int cost[maxn][maxn];
void Dijkstra(int s){
fill(d, d+maxn, INF);
d[s] = 0;
for(int i = 0; i < N; ++i){
int mid = -1, MIN = INF;
for(int j = 0; j < N; ++j){
if(flag[j] == false && d[j] < MIN){
mid = j;
MIN = d[j];
}
}
if(mid == -1) return;
flag[mid] = true;
for(int k = 0; k < N; ++k){
if(flag[k] == false && G[mid][k] != INF){
if(G[mid][k] + d[mid] < d[k]){
d[k] = G[mid][k] + d[mid];
pre[k].clear();
pre[k].push_back(mid);
}else if(G[mid][k] + d[mid] == d[k]){
pre[k].push_back(mid);
}
}
}
}
}
int optC = INF;
vector<int> tmp, res;
void DFS(int v){
if(v == S){
tmp.push_back(v);
int tmpC = 0;
for(int i = tmp.size() - 1; 0 < i; --i){
int id = tmp[i]; int id_next = tmp[i-1];
tmpC += cost[id][id_next];
}
if(tmpC < optC){
optC = tmpC;
res = tmp;
}
tmp.pop_back();
return;
}
tmp.push_back(v);
for(int i = 0; i < pre[v].size(); ++i){
DFS(pre[v][i]);
}
tmp.pop_back();
}
int main(){
scanf("%d %d %d %d", &N, &M, &S, &E);
fill(G[0], G[0]+maxn*maxn,INF);
int c1, c2, dis, cos;
for(int i = 0; i < M; ++i){
scanf("%d %d %d %d", &c1, &c2, &dis, &cos);
G[c1][c2] = dis;
G[c2][c1] = dis;
cost[c1][c2] = cos;
cost[c2][c1] = cos;
}
Dijkstra(S);
DFS(E);
for(int i = res.size() - 1; 0 <= i; --i)
printf("%d ", res[i]);
printf("%d ", d[E]);
printf("%d", optC);
return 0;
}
- T2 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1100, INF = 0x3fffffff;
int g_len[maxn][maxn], g_cost[maxn][maxn], d[maxn];
bool vis[maxn];
vector<int> pre[maxn];
void Dijkstra(int start, int end, int n){
fill(d, d + maxn, INF);
memset(vis, false, sizeof(vis));
d[start] = 0;
for(int i = 0; i < n; ++i){
int now = -1, Min = INF;
for(int j = 0; j < n; ++j){
if(vis[j] == false && d[j] < Min){
Min = d[j];
now = j;
}
}
if(now == -1 || now == end) return;
vis[now] = true;
for(int j = 0; j < n; ++j){
if(vis[j] == false && g_len[now][j] != INF){
if(d[now] + g_len[now][j] < d[j]){
d[j] = d[now] + g_len[now][j];
pre[j].clear();
pre[j].push_back(now);
}else if(d[now] + g_len[now][j] == d[j]){
pre[j].push_back(now);
}
}
}
}
}
vector<int> tmp, ans;
int min_cost = INF;
void DFS(int id, int start){
tmp.push_back(id);
if(id == start){
int tmp_cost = 0;
for(int i = tmp.size()-1; i > 0; --i){
int tnow = tmp[i], tnext = tmp[i-1];
tmp_cost += g_cost[tnow][tnext];
}
if(tmp_cost < min_cost){
min_cost = tmp_cost;
ans = tmp;
}
return;
}
for(int i = 0; i < pre[id].size(); ++i){
int next = pre[id][i];
DFS(next, start);
tmp.pop_back();
}
}
int main(){
int n, m, s, e;
scanf("%d %d %d %d", &n, &m, &s, &e);
fill(g_len[0], g_len[0] + maxn * maxn, INF);
fill(g_cost[0], g_cost[0] + maxn * maxn, INF);
for(int i = 0; i < m; ++i){
int c1, c2;
scanf("%d %d", &c1, &c2);
scanf("%d %d", &g_len[c1][c2], &g_cost[c1][c2]);
g_len[c2][c1] = g_len[c1][c2];
g_cost[c2][c1] = g_cost[c1][c2];
}
Dijkstra(s, e, n);
DFS(e, s);
for(int i = ans.size()-1; i >= 0; --i) printf("%d ", ans[i]);
printf("%d %d", d[e], min_cost);
return 0;
}
- T3 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010, INF = 0x3fffffff;
int G[maxn][maxn], cost[maxn][maxn], d[maxn];
bool vis[maxn];
struct node
{
int id, d;
bool operator < (const node & tmp) const { return d > tmp.d; }
};
vector<int> pre[maxn];
void Dijkstra(int s, int dest, int n)
{
fill(d, d + n, INF);
d[s] = 0;
priority_queue<node> pq;
pq.push(node{s, 0});
while(!pq.empty())
{
node now = pq.top();
pq.pop();
if(now.id == dest) return;
if(vis[now.id]) continue;
vis[now.id] = true;
for(int i = 0; i < n; ++i)
{
if(vis[i] == false && G[now.id][i] != 0)
{
if(now.d + G[now.id][i] < d[i])
{
d[i] = now.d + G[now.id][i];
pre[i].clear();
pre[i].push_back(now.id);
pq.push({i, d[i]});
}else if(now.d + G[now.id][i] == d[i])
{
pre[i].push_back(now.id);
pq.push({i, d[i]});
}
}
}
}
}
vector<int> tmp, ans;
void DFS(int id, int s, int & min_cost)
{
tmp.push_back(id);
if(id == s)
{
int sum_cost = 0, pre = tmp[0];
for(int i = 1; i < tmp.size(); ++i)
{
int now = tmp[i];
sum_cost += cost[pre][now];
pre = now;
}
if(sum_cost < min_cost)
{
min_cost = sum_cost;
ans = tmp;
}
tmp.pop_back();
return; //!!! WRONG:return 回上一层了,这层的id没pop出去
}
for(int i = 0; i < pre[id].size(); ++i)
{
int nex = pre[id][i];
DFS(nex, s, min_cost);
}
tmp.pop_back();
}
int main()
{
int nc, m, s, e;
scanf("%d %d %d %d", &nc, &m, &s, &e);
for(int i = 0; i < m; ++i)
{
int c1, c2, dis, cos;
scanf("%d %d %d %d", &c1, &c2, &dis, &cos);
G[c1][c2] = G[c2][c1] = dis;
cost[c1][c2] = cost[c2][c1] = cos;
}
Dijkstra(s, e, nc);
int Min = INF;
DFS(e, s, Min);
for(int i = ans.size()-1; i >= 0; --i)
{
printf("%d ", ans[i]);
}
printf("%d %d", d[e], Min);
return 0;
}
- BF
#include <bits/stdc++.h>
using namespace std;
const int maxn = 510, INF = 0x3fffffff;
int d[maxn], dc[maxn];
struct node
{
int nex, dis, cost;
};
vector<node> G[maxn];
int pre[maxn];
bool BF(int start, int n)
{
fill(d, d + maxn, INF);
fill(dc, dc + maxn, INF);
d[start] = 0; dc[start] = 0;
for(int i = 0; i < n-1; ++i)
{
bool isUpdate = false;
for(int now = 0; now < n; ++now)
{
for(int j = 0; j < G[now].size(); ++j)
{
int nex = G[now][j].nex;
int dis = G[now][j].dis;
int cost = G[now][j].cost;
if(d[now] + dis < d[nex])
{
d[nex] = d[now] + dis;
dc[nex] = dc[now] + cost;
pre[nex] = now;
isUpdate = true;
}else if(d[now] + dis == d[nex] && dc[now] + cost < dc[nex])
{
dc[nex] = dc[now] + cost;
pre[nex] = now;
isUpdate = true;
}
}
}
if(!isUpdate) return true;
}
for(int now = 0; now < n; ++now)
{
for(int j = 0; j < G[now].size(); ++j)
{
int nex = G[now][j].nex;
int dis = G[now][j].dis;
int cost = G[now][j].cost;
if(d[now] + dis < d[nex])
{
return false;
}
}
}
return true;
}
void Print(int id, int s)
{
if(id == s)
{
printf("%d", id);
return;
}
Print(pre[id], s);
printf(" %d", id);
}
int main()
{
int n, m, s, e;
scanf("%d %d %d %d", &n, &m, &s, &e);
for(int i = 0; i < m; ++i)
{
int v1, v2, len, cost;
scanf("%d %d %d %d", &v1, &v2, &len, &cost);
G[v1].push_back(node{v2, len, cost});
G[v2].push_back(node{v1, len, cost});
}
BF(s, n);
Print(e, s);
printf(" %d %d", d[e], dc[e]);
return 0;
}
- SPFA:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 510, INF = 0x3fffffff;
int d[maxn], dc[maxn];
struct node
{
int nex, dis, cost;
};
vector<node> G[maxn];
int pre[maxn], cnt_inq[maxn];
bool inq[maxn];
bool SPFA(int start, int n)
{
fill(d, d + maxn, INF);
fill(dc, dc + maxn, INF);
d[start] = 0; dc[start] = 0;
queue<int> q;
q.push(start);
inq[start] = true;
cnt_inq[start]++;
while(!q.empty())
{
int now = q.front();
q.pop();
inq[now] = false;
for(int i = 0; i < G[now].size(); ++i)
{
int nex = G[now][i].nex;
int dis = G[now][i].dis;
int cost = G[now][i].cost;
if(d[now] + dis < d[nex])
{
d[nex] = d[now] + dis;
dc[nex] = dc[now] + cost;
pre[nex] = now;
if(inq[nex] == false)
{
q.push(nex);
inq[nex] = true;
cnt_inq[nex]++;
if(cnt_inq[nex] >= n) return true;
}
}else if(d[now] + dis == d[nex] && dc[now] + cost < dc[nex])
{
dc[nex] = dc[now] + cost;
pre[nex] = now;
if(inq[nex] == false)
{
q.push(nex);
inq[nex] = true;
cnt_inq[nex]++;
if(cnt_inq[nex] >= n) return true;
}
}
}
}
return true;
}
void Print(int id, int s)
{
if(id == s)
{
printf("%d", id);
return;
}
Print(pre[id], s);
printf(" %d", id);
}
int main()
{
int n, m, s, e;
scanf("%d %d %d %d", &n, &m, &s, &e);
for(int i = 0; i < m; ++i)
{
int v1, v2, len, cost;
scanf("%d %d %d %d", &v1, &v2, &len, &cost);
G[v1].push_back(node{v2, len, cost});
G[v2].push_back(node{v1, len, cost});
}
SPFA(s, n);
Print(e, s);
printf(" %d %d", d[e], dc[e]);
return 0;
}