Cow Relays
Description
For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a relay race using the T (2 ≤ T ≤ 100) cow trails throughout the pasture.
Each trail connects two different intersections (1 ≤ I1i ≤ 1,000; 1 ≤ I2i ≤ 1,000), each of which is the termination for at least two trails. The cows know the lengthi of each trail (1 ≤ lengthi
≤ 1,000), the two intersections the trail connects, and they know that
no two intersections are directly connected by two different trails.
The trails form a structure known mathematically as a graph.
To run the relay, the N
cows position themselves at various intersections (some intersections
might have more than one cow). They must position themselves properly
so that they can hand off the baton cow-by-cow and end up at the proper
finishing place.
Write a program to help position the cows. Find the shortest path that connects the starting intersection (S) and the ending intersection (E) and traverses exactly N cow trails.
Input
* Line 1: Four space-separated integers: N, T, S, and E
* Lines 2..T+1: Line i+1 describes trail i with three space-separated integers: lengthi , I1i , and I2i
Output
* Line 1: A single integer that is the shortest distance from intersection S to intersection E that traverses exactly N cow trails.
Sample Input
2 6 6 4
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9
Sample Output
10
题意:求经过n条路的最短路。
#include <stdio.h>
#include <stdlib.h>
#define inf 1 << 30
#define maxn 101
#define Min(a, b) a < b ? a : b
int hash[maxn*10], g[maxn], num, ksp[23][maxn][maxn], len[maxn][2];
void set()
{
int i;
num = 0;
for (i = 1; i < maxn; i++)
{
hash[i] = 0;
}
}
int makeHash(int a)
{
if (!hash[a])
{
hash[a] = ++num;
}
return hash[a];
}
int main()
{
int n, t, s, e, h, i, j, k, u, v, w;
while (scanf("%d%d%d%d", &n, &t, &s, &e) != EOF)
{
set();
for (h = 0; h < 23; h++)
{
for (i = 1; i < maxn; i++)
{
for (j = 1; j < maxn; j++)
{
ksp[h][i][j] = inf;
}
}
}
while (t--)
{
scanf("%d%d%d", &w, &u, &v);
u = makeHash(u), v = makeHash(v);
ksp[0][u][v] = ksp[0][v][u] = Min(w, ksp[0][v][u]);
}
s = makeHash(s), e = makeHash(e);
for (h = 1; (1 << h) <= n; h++)//求出i到j经过2的h次方路径的最短路
{
for (i = 1; i <= num; i++)
{
for (j = 1; j <= num; j++)
{
if (ksp[h-1][i][j] < inf)
{
for(k = 1; k <= num; k++)
{
if (ksp[h][i][k] > ksp[h-1][i][j] + ksp[h-1][j][k])
{
ksp[h][i][k] = ksp[h-1][i][j] + ksp[h-1][j][k];
}
}
}
}
}
}
for (i = 1; i <= num; i++)
{
len[i][0] = inf;
}
len[s][0] = 0;
for (h = 0, k = 0; (1 << h) <= n; h++)//组合s到其他节点经过n条路的最短路
{
if (n & (1 << h))//枚举n的二进制上有1的。
{
for (i = 1; i <= num; i++)
{
len[i][k ^ 1] = inf;
}
for (i = 1; i <= num; i++)
{
if (len[i][k] < inf)//这里要判断一下,因为1<<30再加上1<<30就超出int了
{
for (j = 1; j <= num; j++)
{
len[j][k ^ 1] = Min(len[j][k ^1], len[i][k] + ksp[h][i][j]);
}
}
}
k = k ^ 1;
}
}
printf("%d\n", len[e][k]);
}
system("pause");
return 0;
}