【1018 30 Dijkstra dfs】 Public Bike Management

传送门

题意

给给定 \(C_{max},N,S_p,M\)\(N,M\)表示节点个数和边数,\(S_p\) 表示 目标点,\(\frac{cmax}{2}\)表示目标点权值。如果小于就从 \(0\) 进行 send,大于就 back,求从 \(0\)\(S_p\) 的最短路中,按照一下优先级的最短路径

  • send 最少
  • send 相等,back 最少

数据范围

\(1\leq n\leq 500\)

题解

  • 在最短路上经过每个点时,当前的 send/back 就应该能够每个节点调整至完美状态
  • 每个点的 send/back 都是根据上一个节点的计算而来
  • 必须从 0 开始计算各点的值
  • 每一个节点都有后效性,所以不是最优子结构,不能用简单的 \(dp\) 或贪心计算

例子

10 4 4 4
6 7 0 6
0 1 2
1 2 2
2 3 2
3 4 2

Code

#include <bits/stdc++.h>
using namespace std;

#define fi first
#define se second

const int N = 510;

vector<bool> st(N);
vector<pair<int, int>> edge[N];
vector<int> C(N), dis(N), pre[N];
vector<int> path, tmp_path;

int Cmax, n, Sp, m; 
int min_send = INT_MAX, min_back = INT_MAX;

void dijkstra() {
	fill(dis.begin(), dis.end(), INT_MAX);
	dis[0] = 0;

	for (int i = 0; i < n; i++) {
		int t = -1;	
		for (int j = 0; j <= n; j++) {
			if (not st[j] and (t == -1 or dis[j] < dis[t]))
				t = j;
		}
		st[t] = 1;
		for (auto it : edge[t]) {
			auto to = it.fi, w = it.se;
			if (dis[to] > dis[t] + w) {
				dis[to] = dis[t] + w;
				pre[to].clear();
				pre[to].push_back(t);
			} else if (dis[to] == dis[t] + w) {
				pre[to].push_back(t);
			}
		}
	}
}

void dfs(int vertice) {
	tmp_path.push_back(vertice);
	if (vertice == 0) {
		int send = 0, back = 0;
		for (int i = tmp_path.size() - 1; i >= 0; i--) {
			auto it = tmp_path[i];			
			if(C[it] > 0) back += C[it];
			else {
				if(back > abs(C[it])) {
					back += C[it];
				} else {
					send += abs(C[it]) - back;
					back = 0;
				}
			}
		}

		if(send < min_send) {
			min_send = send;
			path = tmp_path;
			min_back = back;
		}
		else if(send == min_send and back < min_back) {
			min_back = back;
			path = tmp_path;
		}
		
		tmp_path.pop_back();
		return;
	}
	for (auto it : pre[vertice]) dfs(it);
	tmp_path.pop_back();
}
int main() {
	cin >> Cmax >> n >> Sp >> m;
	for (int i = 1; i <= n; i++) {
		int x; cin >> x;
		C[i] = x - Cmax / 2;
	}
	while (m--) {
		int u, v, w; cin >> u >> v >> w;
		edge[u].push_back({v, w});
		edge[v].push_back({u, w});
	}
	dijkstra();
	dfs(Sp);

	cout << min_send << ' ';
	for (int i = path.size() - 1; i >= 0; i--) {
		cout << path[i];
		if (i != 0) cout << "->";
		else cout << ' ';
	}
	cout << min_back;
} 

posted @ 2021-02-02 03:46  Hyx'  阅读(29)  评论(0)    收藏  举报