按照题目意思,就是求: 从K点开始,到所有点的最短路径之和。
穷举K即可。 最短路算法,我用的是SPFA。
SPFA+SLF优化:
Compiling... Compile: OK Executing... Test 1: TEST OK [0.005 secs, 3508 KB] Test 2: TEST OK [0.003 secs, 3508 KB] Test 3: TEST OK [0.005 secs, 3508 KB] Test 4: TEST OK [0.005 secs, 3508 KB] Test 5: TEST OK [0.011 secs, 3508 KB] Test 6: TEST OK [0.022 secs, 3508 KB] Test 7: TEST OK [0.049 secs, 3508 KB] Test 8: TEST OK [0.051 secs, 3508 KB] Test 9: TEST OK [0.078 secs, 3508 KB] Test 10: TEST OK [0.084 secs, 3508 KB] All tests OK.
/* TASK:butter LANG:C++ */ #include <cstdio> #include <cstring> #include <queue> using namespace std; int cows, pastures, paths; const int savebuff = 50; int a[500 + savebuff], f[1000]; bool vis[1000]; int ans = 0x7fffffff; struct edge { int dot, dis; edge *next; edge() { dot = dis = -1; next = NULL; } edge(int DOT_, int DIS_, edge *NEXT_) { dot = DOT_; dis = DIS_; next = NEXT_; } }*x[800 + savebuff]; inline void insert(int A, int B, int dis) { x[A] = new edge(B, dis, x[A]); } deque<int>q; void SPFA(int s) { q.push_back(s); memset(f, 60, sizeof(f)); memset(vis, false, sizeof(vis)); f[s] = 0; vis[s] = true; while (!q.empty()) { int now = q.front(); vis[now] = false; q.pop_front(); for (edge *i = x[now]; i; i = i -> next) { int will = i -> dot; int cost = i -> dis; if (f[now] + cost < f[will]) { f[will] = f[now] + cost; if (!vis[will]) { if (!q.empty() && f[will] < f[q.front()]) q.push_front(will); else q.push_back(will); } } } } int tmpans = 0; for (int i = 0; i != cows; ++ i) tmpans += f[a[i]]; if (tmpans < ans) ans = tmpans; } int main() { freopen("butter.in","r",stdin); freopen("butter.out","w",stdout); memset(x, NULL, sizeof(x)); scanf("%d%d%d", &cows, &pastures, &paths); for (int i = 0; i != cows; ++ i) scanf("%d", a+i); while (paths--) { int ta, tb, tc; scanf("%d%d%d", &ta, &tb, &tc); insert(ta, tb, tc); insert(tb, ta, tc); } for (int i = 1; i <= pastures; ++ i) SPFA(i); printf("%d\n", ans); return 0; }
==============
SPFA的LLL+SLF优化: 速度更慢,就不贴代码了。