HDU 5636 Shortest Path
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5636
题解:
1、暴力枚举:
#include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; typedef long long LL; const int maxn = 1e5 + 10; const int mod = 1e9 + 7; int n, m; int a[11], b[11]; int main() { int T; scanf("%d", &T); while (T--) { scanf("%d%d", &n, &m); for (int i = 0; i < 3; i++) scanf("%d%d", a + i, b + i); LL ans = 0; int x, y; for (int i = 1; i <= m; i++) { scanf("%d%d", &x, &y); //一条新路线都不走 int tmp = abs(x - y); //只走一条 for (int j = 0; j < 3; j++) { tmp = min(tmp, abs(x - a[j]) + abs(b[j] - y) + 1); tmp = min(tmp, abs(x - b[j]) + abs(a[j] - y) + 1); } //走两条 for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { if (j == k) continue; //x -> j开头 -> j结尾 -> k开头 -> k结尾 -> y tmp = min(tmp, abs(x - a[j]) + abs(b[j] - a[k]) + abs(b[k] - y) + 2); //x -> j开头 -> j结尾 -> k结尾 -> k开头 -> y tmp = min(tmp, abs(x - a[j]) + abs(b[j] - b[k]) + abs(a[k] - y) + 2); //x -> j结尾 -> j开头 -> k开头 -> k结尾 -> y tmp = min(tmp, abs(x - b[j]) + abs(a[j] - a[k]) + abs(b[k] - y) + 2); //x -> j结尾 -> j开头 -> k结尾 -> k开头 -> y tmp = min(tmp, abs(x - b[j]) + abs(a[j] - b[k]) + abs(a[k] - y) + 2); } } //走三条 for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { if (j == k) continue; for (int w = 0; w < 3; w++) { if (w == j || w == k) continue; tmp = min(tmp, abs(x - a[j]) + abs(b[j] - a[k]) + abs(b[k] - a[w]) + abs(b[w] - y) + 3); tmp = min(tmp, abs(x - a[j]) + abs(b[j] - a[k]) + abs(b[k] - b[w]) + abs(a[w] - y) + 3); tmp = min(tmp, abs(x - a[j]) + abs(b[j] - b[k]) + abs(a[k] - a[w]) + abs(b[w] - y) + 3); tmp = min(tmp, abs(x - a[j]) + abs(b[j] - b[k]) + abs(a[k] - b[w]) + abs(a[w] - y) + 3); tmp = min(tmp, abs(x - b[j]) + abs(a[j] - a[k]) + abs(b[k] - a[w]) + abs(b[w] - y) + 3); tmp = min(tmp, abs(x - b[j]) + abs(a[j] - a[k]) + abs(b[k] - b[w]) + abs(a[w] - y) + 3); tmp = min(tmp, abs(x - b[j]) + abs(a[j] - b[k]) + abs(a[k] - a[w]) + abs(b[w] - y) + 3); tmp = min(tmp, abs(x - b[j]) + abs(a[j] - b[k]) + abs(a[k] - b[w]) + abs(a[w] - y) + 3); } } } ans += ((LL)i*tmp)%mod; ans %= mod; } printf("%lld\n", ans); } return 0; }
2、floyd:
对三条新边对应的关键顶点重新建图,跑一遍floyd最短路,对于查询(xi,yi),我们枚举任意两个关键节点(aj,bj),求min(|xi-aj|+len+|bj-yi|),其中len表示新图里面aj到bj的最短距离。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 typedef long long LL; 8 9 const int maxn = 1e5 + 10; 10 const int mod = 1e9 + 7; 11 const int INF = 0x3f3f3f3f; 12 13 int n, m; 14 int a[11],mat[11][11]; 15 16 void init() { 17 memset(mat, 0x3f, sizeof(mat)); 18 for (int i = 0; i < 11; i++) mat[i][i] = 0; 19 } 20 21 int main() { 22 int tc; 23 scanf("%d", &tc); 24 while (tc--) { 25 init(); 26 scanf("%d%d", &n, &m); 27 for (int i = 0; i < 3; i++) { 28 scanf("%d%d", a + i, a + i + 3); 29 } 30 //新图 31 for (int i = 0; i < 6; i++) { 32 for (int j = 0; j < 6; j++) { 33 mat[i][j] = abs(a[i] - a[j]); 34 } 35 } 36 for (int i = 0; i < 3; i++) { 37 mat[i][i + 3] = mat[i + 3][i] = 1; 38 } 39 //floyd 40 for (int k = 0; k < 6; k++) { 41 for (int i = 0; i < 6; i++) { 42 for (int j = 0; j < 6; j++) { 43 mat[i][j] = min(mat[i][j], mat[i][k] + mat[k][j]); 44 } 45 } 46 } 47 LL ans = 0; 48 for (int i = 1; i <= m; i++) { 49 int x, y; 50 scanf("%d%d", &x, &y); 51 LL z = abs(x-y); 52 //枚举所有情况 53 for (int i = 0; i < 6; i++) { 54 for (int j = 0; j < 6; j++) { 55 int tmp = abs(x - a[i]) + mat[i][j] + abs(a[j] - y); 56 z = min(z, (LL)tmp); 57 } 58 } 59 ans += z*i; 60 ans %= mod; 61 } 62 printf("%lld\n", ans); 63 } 64 return 0; 65 }