ZOJ-1655 Transport Goods 最短路
该题又是一个牵涉到节点之间关系通过乘法建立的关系,通过求对数将关系由乘法变为加法应该是可以的。可惜无法无法AC。改为直接相乘却过了。
AC代码:
#include <iostream> #include <cmath> #include <cstdlib> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> #include <iomanip> using namespace std; /* 一个网络的运送问题,简化之后就是一个最短路问题 需要计算从N点出发到各个点的最大保有率 */ const int MaxN = 105; const int NONE = 2; int N, M, trans[MaxN]; double Map[MaxN][MaxN]; bool vis[MaxN]; double rate[MaxN]; void spfa(int N) { memset(vis, 0, sizeof (vis)); // 初始化到N点的保有率为无意义态,这个无意义态必须要求和可能出现的状态不相冲突 for (int i = 1; i <= N; ++i) { rate[i] = NONE; } rate[N] = 1.0; queue<int>q; q.push(N); vis[N] = true; while (!q.empty()) { int v = q.front(); vis[v] = false; q.pop(); for (int i = 1; i <= N; ++i) { if (Map[v][i] != NONE) { // 如果有边的话 if (rate[i] == NONE) { // 如果未被更新 rate[i] = rate[v] * Map[v][i]; q.push(i); vis[i] = true; } else if (rate[v] * Map[v][i] > rate[i]){ rate[i] = rate[v] * Map[v][i]; if (!vis[i]) { q.push(i); vis[i] = true; } } } } } } int main() { while (cin >> N >> M) { for (int i = 1; i <= N; ++i) { for (int j = 1; j <= N; ++j) { Map[i][j] = NONE; // 1表示两点之间没有路相连 } } for (int i = 1; i < N; ++i) { cin >> trans[i]; // 保留各个节点需要运送的量为多少 } int a, b; double c; for (int i = 0; i < M; ++i) { cin >> a >> b >> c; // 读取边的信息,题目给定的c是一个损失率 c = 1 - c; // 得到保有率 if (Map[a][b] == NONE) { Map[a][b] = Map[b][a] = c; } else { Map[a][b] = Map[b][a] = max(c, Map[a][b]); } } spfa(N); double tot = 0; for (int i = 1; i < N; ++i) { if (rate[i] != NONE) { tot += trans[i] * rate[i]; } } cout.setf(ios::fixed); cout << setprecision(2); cout << tot << endl; } return 0; }
WA代码:
View Code
#include <iostream> #include <cmath> #include <cstdlib> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> #include <iomanip> using namespace std; /* 一个网络的运送问题,简化之后就是一个最短路问题 需要计算从N点出发到各个点的最大保有率 */ const int MaxN = 105; const int NONE = 1; int N, M, trans[MaxN]; double Map[MaxN][MaxN]; bool vis[MaxN]; double rate[MaxN]; void spfa(int N) { memset(vis, 0, sizeof (vis)); // 初始化到N点的保有率为无意义态,这个无意义态必须要求和可能出现的状态不相冲突 for (int i = 1; i <= MaxN; ++i) { rate[i] = NONE; } rate[N] = log(1.0); queue<int>q; q.push(N); vis[N] = true; while (!q.empty()) { int v = q.front(); vis[v] = false; q.pop(); for (int i = 1; i <= N; ++i) { if (Map[v][i] != NONE) { // 如果有边的话 if (rate[i] == NONE) { // 如果未被更新 rate[i] = rate[v] + Map[v][i]; q.push(i); vis[i] = true; } else if (rate[v] + Map[v][i] > rate[i]){ rate[i] = rate[v] + Map[v][i]; if (!vis[i]) { q.push(i); vis[i] = true; } } } } } } int main() { while (cin >> N >> M) { for (int i = 1; i <= N; ++i) { for (int j = 1; j <= N; ++j) { Map[i][j] = NONE; // 1表示两点之间没有路相连 } } for (int i = 1; i < N; ++i) { cin >> trans[i]; // 保留各个节点需要运送的量为多少 } int a, b; double c; for (int i = 0; i < M; ++i) { cin >> a >> b >> c; // 读取边的信息,题目给定的c是一个损失率 c = 1 - c; // 得到保有率 if (Map[a][b] == NONE) { Map[a][b] = Map[b][a] = log(c); // 求指数,将概率连乘变为加法 } else { Map[a][b] = Map[b][a] = max(log(c), Map[a][b]); } } spfa(N); double tot = 0; for (int i = 1; i < N; ++i) { if (rate[i] != NONE) { tot += trans[i] * exp(rate[i]); } } cout.setf(ios::fixed); cout << setprecision(2); cout << tot << endl; } return 0; }