用贪心的思想,25分,5和7测试点错误,原因如下
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 550;
int c, n, e, m;
int G[maxn][maxn], vis[maxn], d[maxn];
int weight[maxn], w[maxn];
vector<int> path[maxn];
void dijkstra(int e) {
fill(vis, vis + maxn, 0);
fill(d, d + maxn, INF);
d[0] = 0;
fill(w, w + maxn, 0);
w[0] = 0;
for (int k = 0; k < n; k++)
{
int u = -1, Min = INF;
for (int i = 0; i < n; i++) {
if (!vis[i] && d[i] < Min) {
u = i;
Min = d[i];
}
}
if (u == -1) { return; }
vis[u] = 1;
for (int v = 0; v < n; v++) {
if (!vis[v] && G[u][v] != INF) {
if (d[u] + G[u][v] < d[v]) {
d[v] = d[u] + G[u][v];
path[v].clear();
path[v].push_back(u);
w[v] = w[u] + weight[v];
}
else if (d[u] + G[u][v] == d[v]) {
int a = w[u] + weight[v], b = w[v];//错误方法,见https://blog.csdn.net/weixin_43116322/article/details/103840390
if ((b < 0 && a > b && a <= 0) || (b > 0 && a < b)) {//不可以用贪心,因为贪心只考虑v节点之前的,故只能用dfs
w[v] = w[u] + weight[v];
path[v].clear();
path[v].push_back(u);
}
}
}
}
}
}
vector<int> ans;
void Print(int e) {
ans.push_back(e);
if (e == 0) {
int l = ans.size();
for (int i = l - 1; i > 0; i--) {
cout << ans[i] << "->";
}
cout << ans[0] << ' ';
return;
}
Print(path[e][0]);
}
int main() {
fill(G[0], G[0] + maxn * maxn, INF);
cin >> c >> n >> e >> m;
c /= 2;
for (int i = 1; i <= n; i++) {
int t;
cin >> t;
weight[i] = t - c;
}
for (int i = 1; i <= m; i++) {
int a, b, t;
cin >> a >> b >> t;
G[a][b] = G[b][a] = t;
}
n++;
dijkstra(e);
if (w[e] < 0) {
cout << (-w[e]) << ' ';
Print(e);
cout << '0';
}
else {
cout << "0 ";
Print(e);
cout << w[e];
}
return 0;
}
正确解答
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 550;
int c, n, e, m;
int G[maxn][maxn], vis[maxn], d[maxn];
int weight[maxn];
vector<int> path[maxn];
void dijkstra(int e) {
fill(vis, vis + maxn, 0);
fill(d, d + maxn, INF);
d[0] = 0;
for (int k = 0; k < n; k++)
{
int u = -1, Min = INF;
for (int i = 0; i < n; i++) {
if (!vis[i] && d[i] < Min) {
u = i;
Min = d[i];
}
}
if (u == -1) { return; }
vis[u] = 1;
for (int v = 0; v < n; v++) {
if (!vis[v] && G[u][v] != INF) {
if (d[u] + G[u][v] < d[v]) {
d[v] = d[u] + G[u][v];
path[v].clear();
path[v].push_back(u);
}
else if (d[u] + G[u][v] == d[v]) {
path[v].push_back(u);
}
}
}
}
}
vector<int> ans, temp;
int ansNeed = INF, ansBack = INF;
void dfs(int e) {//注意!!!每一站多的车辆只能放到后面一站去,而不能补充前面车站中少的数目。否则5、7测试点错误
temp.push_back(e);
if (e == 0) {
int need = 0, back = 0;
for (int i = temp.size() - 1; i >= 0; i--) {
int t = weight[temp[i]];
if (t >= 0) {//该点数量过多
back += t;
}
else {//该点数量过少
t = -t;
if (back < t) {
need += (t - back);
back = 0;
}
else {
back -= t;
}
}
}
if (need < ansNeed) {
ansNeed = need;
ansBack = back;
ans = temp;
}
else if (need == ansNeed && back < ansBack) {
ansBack = back;
ans = temp;
}
}
for (int i = 0; i < path[e].size(); i++) {
dfs(path[e][i]);
temp.pop_back();
}
}
void Print(int e) {
int l = ans.size();
for (int i = l - 1; i > 0; i--) {
cout << ans[i] << "->";
}
cout << ans[0] << ' ';
}
int main() {
fill(G[0], G[0] + maxn * maxn, INF);
cin >> c >> n >> e >> m;
c /= 2;//转化最大值为标准值
for (int i = 1; i <= n; i++) {
int t;
cin >> t;
weight[i] = t - c;//存储目前数量与标准数量的差
}
for (int i = 1; i <= m; i++) {
int a, b, t;
cin >> a >> b >> t;
G[a][b] = G[b][a] = t;
}
n++;
dijkstra(e);
dfs(e);
cout << ansNeed << ' ';
Print(e);
cout << ansBack;
return 0;
}