poj 3613(还是不懂,以后再看看)

题意:给定一个T(2 <= T <= 100)条边的无向图,求S到E恰好经过N(2 <= N <= 1000000)条边的最短路。

以前一直没仔细想过floyd算法,觉得很简单,今天做这题的时候,看网上的报告都有一句:floyd是每次使用一个中间点k去更新i,j之间的距离,那么更新成功表示i,j之间恰有一个点k时的最短路,如果做N - 1次floyd那么不就是i,j之间借助N - 1 个点时的最短路了。看了很久不明白为什么。也对floyd的最外围的那个k

回到这题,floyd算法是对自身矩阵更新,而这道题却是更新到另一个矩阵上,所以不会出现刚更新过的值又来更新。。例如下面代码的b.mat[1][3] c.mat[3][5]就分别代表上面的dis[1][3],dis[3][5].我们不需要知道tmp.mat[1][5]已经有的点个数。(即已经更新的次数。)只知道,这次更新会加入一个3到他们中间。所以更新k-1次就行。

    #include   
    #include   
    #include   
    using namespace std;  
      
    int K, n, m, s, t, x, y, z;  
    map mp;  
      
    struct Matrix {  
        int a[205][205];  
        Matrix operator * (Matrix &r) {  
            Matrix c;  
            memset(c.a, 0x3f, sizeof c.a);  
            for(int i = 1; i <= n; i++)  
            for(int j = 1; j <= n; j++)  
            for(int k = 1; k <= n; k++)  
                c.a[i][j] = min(c.a[i][j], a[i][k] + r.a[k][j]);  
            return c;  
        }  
    }st, ans;  
      
    void power() {  
        ans = st, K--;  
        while(K) {  
            if(K & 1) ans = ans * st;  
            st = st * st;  
            K >>= 1;  
        }  
    }  
      
    int main() {  
        scanf("%d%d%d%d", &K, &m, &s, &t);  
        memset(st.a, 0x3f, sizeof st.a);  
        while(m--) {  
            scanf("%d%d%d", &z, &x, &y);  
            if(mp[x]) x = mp[x]; else x = mp[x] = ++n;  
            if(mp[y]) y = mp[y]; else y = mp[y] = ++n;  
            st.a[x][y] = st.a[y][x] = z;  
        }  
        power();  
        printf("%d", ans.a[mp[s]][mp[t]]);  
        return 0;  
    }  


你可能感兴趣的:(图论)