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;
}