题目链接:http://poj.org/problem?id=3613

Cow Relays
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3199   Accepted: 1240

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

 

有t条道路,现有好多牛进行接力跑,给出起点和终点,问从起点到终点恰好有n头牛参与赛跑(每头牛只跑其中的一条道路)的最短路程是多少。

本题可以转化为矩阵的“乘法”。

由于点可能很大,先进行一次离散,之后根据每条路的长度就能建一个矩阵。

我们让这个矩阵再“乘以”这个矩阵,这时我们不用乘而是用加 c[i][j]=a[i][h]+a[h][j] (1<=h<=n);

可以理解为从i经过点h到j,c[i][j]就表示所走的路程。如果我们在(1<=h<=n)中取c[i][j]最小的值, c[i][j]就可以理解为从i到j恰好走过两条道路的最短路程。

那么题目所求即是n个矩阵a 作“乘法”,这个地方可以和矩阵快速幂联系起来。

code:

View Code
 1 #include<stdio.h>
2 #include<string.h>
3 # define N 205
4 int st[N],t,vis[10*N];
5 int a[N][N],goal[N][N];
6 struct node{
7 int a,b,c;
8 }s[N];
9 int find(int x)
10 {
11 int left,right,mid;
12 left=1;
13 right=t;
14 while(right>=left)
15 {
16 mid=(right+left)/2;
17 if(st[mid]==x) return mid;
18 if(st[mid]>x) right=mid-1;
19 else left=mid+1;
20 }
21 return 0;
22 }
23 void mod(int k)
24 {
25 int i,j,h,n,ans;
26 int c[N][N];
27 n=t;
28 for(i=1;i<=n;i++)
29 for(j=1;j<=n;j++)
30 goal[i][j]=a[i][j];
31 k--;
32 while(k>=1)
33 {
34 if(k%2)
35 {
36 memset(c,-1,sizeof(c));
37 for(i=1;i<=n;i++)
38 for(j=1;j<=n;j++)
39 {
40 for(h=1;h<=n;h++)
41 {
42 if(a[i][h]==-1 || goal[h][j]==-1) continue;
43 ans=a[i][h]+goal[h][j];
44 if(c[i][j]==-1 || c[i][j]>ans) c[i][j]=ans;
45 }
46 }
47 for(i=1;i<=n;i++)
48 for(j=1;j<=n;j++)
49 goal[i][j]=c[i][j];
50 }
51 memset(c,-1,sizeof(c));
52 for(i=1;i<=n;i++)
53 for(j=1;j<=n;j++)
54 {
55 for(h=1;h<=n;h++)
56 {
57 if(a[i][h]==-1 || a[h][j]==-1) continue;
58 ans=a[i][h]+a[h][j];
59 if(c[i][j]==-1 || c[i][j]>ans) c[i][j]=ans;
60 }
61 }
62 for(i=1;i<=n;i++)
63 for(j=1;j<=n;j++)
64 a[i][j]=c[i][j];
65 k/=2;
66 }
67 }
68 int main()
69 {
70 int i,k,n,from,to,ans1,ans2;
71 while(scanf("%d%d%d%d",&k,&n,&from,&to)!=EOF)
72 {
73 memset(vis,0,sizeof(vis));
74 for(i=1;i<=n;i++)
75 {
76 scanf("%d%d%d",&s[i].c,&s[i].a,&s[i].b);
77 vis[s[i].a]=1;
78 vis[s[i].b]=1;
79 }
80 t=0;
81 for(i=1;i<=1000;i++)
82 if(vis[i]) st[++t]=i;
83 memset(a,-1,sizeof(a));
84 for(i=1;i<=n;i++)
85 {
86 ans1=find(s[i].a);
87 ans2=find(s[i].b);
88 a[ans1][ans2]=a[ans2][ans1]=s[i].c;
89 }
90 mod(k);
91 ans1=find(from);
92 ans2=find(to);
93 printf("%d\n",goal[ans1][ans2]);
94 }
95 return 0;
96 }

 

 

 

 

posted on 2011-10-31 19:58  奋斗青春  阅读(922)  评论(0编辑  收藏  举报