PAT A1030 Travel Plan

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
wordmeaning
destinationn. 目的地, 终点
  • 思路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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值