1018 Public Bike Management(DFS+dijkstra,最短路径加附加条件判断模板)

1018 Public Bike Management(DFS+dijkstra,最短路径加附加条件判断模板)

There is a public bike service in Hangzhou City which provides great convenience to the tourists from all over the world. One may rent a bike at any station and return it to any other stations in the city.

The Public Bike Management Center (PBMC) keeps monitoring the real-time capacity of all the stations. A station is said to be in perfect condition if it is exactly half-full. If a station is full or empty, PBMC will collect or send bikes to adjust the condition of that station to perfect. And more, all the stations on the way will be adjusted as well.

When a problem station is reported, PBMC will always choose the shortest path to reach that station. If there are more than one shortest path, the one that requires the least number of bikes sent from PBMC will be chosen.
在这里插入图片描述
在这里插入图片描述
这个问题可以抽象为pat的一类模板:多条最短路径同时存在,给出其他条件,在多条最短路径中找到性能最优的一条。
通过dijkstra找到多条最短路径,用二维vector存储,之后再通过DFS重走各条最短路径,在重走的过程中记录路径上的总资源,跟全局的最优解比较,完成替换,得到路径。

#include<iostream>
#include<vector>
using namespace std;
const int Max = 1000000;
int G[501][501],dist[501],w[501];
int minSend = Max, minBack = Max;
bool visited[501];
int C, M,S, K;
vector<int> pre[501],temppath,path;

void DFS(int v) {
	temppath.push_back(v);
	if (v == 0) {
		int send = 0, back = 0;
		for (int i = temppath.size()-1; i>=0 ; i--) {
			int id = temppath[i];
			if (w[id] > 0)
				back += w[id];
			else
				if (0 - w[id] < back) {
					back += w[id];
				}
				else {
					send -= (back + w[id]);
					back = 0;
				}
		}
		if (send < minSend) {
			minSend = send;
			minBack = back;
			path = temppath;
		}else
			if (send == minSend && back < minBack) {
				minBack = back;
				path = temppath;
			}
		temppath.pop_back();
		return;
	}
	for (int i = 0; i < pre[v].size(); i++)
		DFS(pre[v][i]);
	temppath.pop_back();
}
int main()
{
	cin >> C >> M >> S >> K;
	fill(G[0], G[0] + 501 * 501, Max);
	fill(dist, dist + 501, Max);
	for (int i = 1; i <= M; i++)
	{
		scanf("%d", &w[i]);
		w[i] -= C / 2;
	}
	for (int i = 0; i < K; i++) {
		int a, b, l;
		scanf("%d %d %d", &a, &b, &l);
		G[a][b] = G[b][a] = l;
	}
	dist[0] = 0;
	while (true) {
		int v = -1, min = Max;
		for (int i = 0; i <= M; i++) {
			if (!visited[i] && dist[i] < min) {
				min = dist[i];
				v = i;
			}
		}
		if (v == -1)break;
		visited[v] = true;
		for (int i = 0; i <= M; i++) {
			if (!visited[i] && G[v][i] != Max) {
				if (dist[i] > dist[v] + G[v][i]) {
					dist[i] = dist[v] + G[v][i];
					pre[i].clear();
					pre[i].push_back(v);
				}else
					if (dist[i] == dist[v] + G[v][i]) {
						pre[i].push_back(v);
					}
			}
		}
	}
	DFS(S);
	printf("%d 0", minSend);
	for (int i = path.size() - 2; i >= 0; i--)
		printf("->%d", path[i]);
	printf(" %d", minBack);
	return 0;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值