poj 3613 Cow Relays(矩阵的图论意义)

题解

用一个矩阵来表示一个图的边的存在性,即矩阵C【i,j】=1表示有一条从i到j的有向边C【i,j】=0表示没有从i到j的边。这个矩阵的k次方后C【i,j】就表示有多少条从i到j恰好经过k条边的路径。

在此题中我们赋予边权值并把矩阵乘法中的+改为min这样这个矩阵的k次方后C【i,j】就表示从i到j恰好经过k条边的最短路径。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=300;
 8 int n,t,s,e,u[N],v[N],w[N],b[N],a[N],ma[3000],num,tot;
 9 struct jz{
10     int a[N][N];
11 }x;
12 jz jzc(jz a,jz b){
13     jz c;
14     for(int i=1;i<=num;i++)
15         for(int j=1;j<=num;j++){
16             c.a[i][j]=999999999;
17         }
18     for(int i=1;i<=num;i++)
19         for(int j=1;j<=num;j++)
20             for(int k=1;k<=num;k++){
21                 c.a[i][j]=min(c.a[i][j],a.a[i][k]+b.a[k][j]);
22             }
23     return c;
24 }
25 jz ksm(jz a,int k){
26     jz ans=a;
27     k--;
28     while(k){
29         if(k&1){
30             ans=jzc(ans,a);
31         }
32         k>>=1;
33         a=jzc(a,a);
34     }
35     return ans;
36 }
37 int main(){
38     scanf("%d%d%d%d",&n,&t,&s,&e);
39     for(int i=1;i<=t;i++){
40         scanf("%d%d%d",&w[i],&u[i],&v[i]);
41         a[++tot]=u[i];
42         b[tot]=u[i];
43         a[++tot]=v[i];
44         b[tot]=v[i];
45     }
46     sort(b+1,b+1+tot);
47     num=unique(b+1,b+1+tot)-(b+1);
48     for(int i=1;i<=tot;i++){
49         ma[a[i]]=lower_bound(b+1,b+1+num,a[i])-b;
50     }
51     for(int i=1;i<=num;i++)    
52         for(int j=1;j<=num;j++)
53             x.a[i][j]=999999999;
54     for(int i=1;i<=t;i++){
55         x.a[ma[u[i]]][ma[v[i]]]=min(x.a[ma[u[i]]][ma[v[i]]],w[i]);
56         x.a[ma[v[i]]][ma[u[i]]]=min(x.a[ma[v[i]]][ma[u[i]]],w[i]);
57     }
58     x=ksm(x,n);
59     printf("%d",x.a[ma[s]][ma[e]]);
60     return 0;
61 } 
62 /*
63 2 6 6 4
64 11 4 6
65 4 4 8
66 8 4 9
67 6 6 8
68 2 6 9
69 3 8 9
70 */
View Code

 

posted @ 2018-07-28 09:03  Xu-daxia  阅读(377)  评论(0编辑  收藏  举报