题目
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=607&page=show_problem&problem=4763
分析
Floyd+图上按链DP
对于每条链,从起点到其他所有点连边,求floyd
首先只有两种情况,一是A>B,C->D,这种情况直接floyd就可以
另一情况时A->D,C->B,这种情况要求交于一点,又要保证沿着链走,所以枚举一条链,然后在链上做DP
设f[i][0]表示A->D与C->B相交在i的A->D的最短距离
设f[i][1]表示C->B与A->D相交在i的C->B的最短距离
那么转移方程:
f[i][0]=min{dist[A][src]+cost[x]+dist[next][D]}
f[i][1]=min{dist[C][src]+cost[x]+dist[next][B]}
x为枚举的链,src为链的起点,next为i在链上的后继
最后答案为min{dist[A][B]+dist[C][D],min{dist[A][i]+dist[i][D],f[i][0]}+min{dist[C][i]+dist[i][B],f[i][1]}}
时间复杂度O(NL)
L为所有链的总长度
代码
/************************************************** * Problem: LA 6751 * Author: clavichord93 * State: Accepted **************************************************/ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <vector> using namespace std; const int INF = 0x3f3f3f3f; template <class T> inline void gmin(T &a, T b) { if (a > b) { a = b; } } const int MAX_N = 105; const int MAX_M = 10005; int n, m; int A, B, C, D; int cost[MAX_M]; vector<int> flight[MAX_M]; int graph[MAX_N][MAX_N]; int f[MAX_N][2]; int main() { #ifdef LOCAL_JUDGE freopen("in.txt", "r", stdin); #endif while (scanf("%d %d %d %d %d %d", &n, &m, &A, &B, &C, &D), n || m || A || B || C || D) { memset(graph, 0x3f, sizeof(graph)); for (int i = 1; i <= n; i++) { graph[i][i] = 0; } for (int i = 0; i < m; i++) { int cnt, src; scanf("%d %d %d", &cost[i], &cnt, &src); flight[i].clear(); flight[i].push_back(src); for (int j = 0; j < cnt; j++) { int dst; scanf("%d", &dst); flight[i].push_back(dst); gmin(graph[src][dst], cost[i]); } } for (int k = 1; k <= n; k++) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { gmin(graph[i][j], graph[i][k] + graph[k][j]); } } } memset(f, 0x3f, sizeof(f)); for (int i = 0; i < m; i++) { int src = flight[i][0]; int size = flight[i].size(); int dp0 = INF; int dp1 = INF; for (int j = size - 1; j >= 0; j--) { int dst = flight[i][j]; gmin(dp0, graph[A][src] + cost[i] + graph[dst][D]); gmin(f[dst][0], dp0); gmin(dp1, graph[C][src] + cost[i] + graph[dst][B]); gmin(f[dst][1], dp1); } } int ans = INF; gmin(ans, graph[A][B] + graph[C][D]); for (int i = 1; i <= n; i++) { gmin(ans, min(graph[A][i] + graph[i][D], f[i][0]) + min(graph[C][i] + graph[i][B], f[i][1])); } if (ans == INF) { printf("Impossible!\n"); } else { printf("%d\n", ans); } } return 0; }