poj3613 过K条边最短路 floyed

解题报告

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

题目大意 :给定一个图G,求恰过K条边的最短路。

题目类型 floyed + 矩阵快速幂

思路 :离散数学里有著名定理,当原图G的权值仅为01时(即联通或不联通)G^k就是每两个点ij的恰好经过K条边的路。这个题是否也能如此呢?设定状态f[i][j][k]表示从ijk条边的最短路,初始条件f[i][j][1] = map[i][j];

àf[i][j][k] = min( f[i][p][k – 1] + map[p][j] )(权值都大于0

àfoyled类似,由于迭代关系,[k]维可以省略

àf2[i][j] = min( f1[i][p] + map[p][j] ) 由于数据规模太大,还是不够。

à观察矩阵乘法形式temp[i][j] = a[i][j] * b[j][k],发现非常相

à利用矩阵快速幂,求K foyled,可以的到解。

为什么是对的呢? 分析一下.

当我们把矩阵乘法里的“相乘”和“求和”改成“相加”和“min()”后,运算仍然满足结合率,即仍然可以使用快速幂的方法。

详见2008. 俞华程《矩阵乘法在信息学中的应用》

注意 :路径长度最大为1000000000.注意最大值初始化。又在这里wa了。

提交情况 wrong answer 5 INF初始化太小)

                      Accepted 1

经验与收获:很早听说了此题,今天终于过了,虽然是看的解题报告,不过感觉还是不错的。

AC code

#include

#include

 

#define MIN(a, b) ((a) < (b) ? (a) : (b))

#define MAXI 1010

#define MAXT 110

#define INF 1005000000

intset[MAXI];

 

struct LINE{

    int line[MAXT];

};

 

struct ROW{

    LINE row[MAXT];

};

ROW map;

int point;

 

voidclear(ROW &temp){

    int i, j;

    for(i = 0; i < MAXT; i ++)

       for(j = 0; j < MAXT; j ++)

           temp.row[i].line[j] = INF;

}

ROW Matrix_multi(ROW A, ROW B){

    int i, j, k;

    ROW temp;

    clear(temp);

    for(k = 1; k <= point; k ++)

       for(i = 1; i <= point; i ++)

           for(j = 1; j <= point; j ++)

                  temp.row[i].line[j] = MIN(temp.row[i].line[j], A.row[i].line[k] + B.row[k].line[j]);

    return temp;

}

intGet_ans(int s, int e, int n){

    int i, j;

    ROW ans;

    clear(ans);

    for(i = 0; i < MAXT; i ++) ans.row[i].line[i] = 0;

    while(n){

       if(n & 1) ans = Matrix_multi(ans, map);

       map = Matrix_multi(map, map);

       n >>= 1;

    }

    return ans.row[set[s]].line[set[e]];

}

int main(){

    int n, t, s, e, x, y, z, i, ans;

    scanf("%d %d %d %d", &n, &t, &s, &e);

    memset(set, 0, sizeof(set));

    clear(map);

    point = 0;

    for(i = 0; i < t; i ++){

       scanf("%d %d %d", &z, &x, &y);

       if(!set[x]) set[x] = ++point;

       if(!set[y]) set[y] = ++point;

       map.row[set[x]].line[set[y]] = z;

       map.row[set[y]].line[set[x]] = z;

    }

    ans = Get_ans(s, e, n);

    printf("%d\n", ans);

    return 0;

}

你可能感兴趣的:(acm)