Loading

Poj 3613 Cow Relays (图论)

Poj 3613 Cow Relays (图论)

题目大意

给出一个无向图,T条边,给出N,S,E,求S到E经过N条边的最短路径长度
理论上讲就是给了有n条边限制的最短路

solution

最一开始想到是的去直接统计最短路经过了多少条边,结果,,,
还是太年轻了。。。
不过,看数据范围只有1000,那么floyd是首选
回顾Floyd算法流程,其中的i到j松弛操作是通过k完成的
那么松弛一次就利用一个k点,我现在要经过n条边,那么松弛n次即可

详细说就是更新一次之后,把f[i][j]拷贝到原来的a[i][j]中,然后再松弛,此时i、j之间就已经松弛了两次了
以此类推,利用矩阵快速幂优化

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
// #define int long long
using namespace std;

inline int read(){
	int x = 0, w = 1;
	char ch = getchar();
	for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return x * w;
}

int s, t, n, e;
int tot;
const int maxn = 555;
struct node{
    int a[maxn][maxn];
    node operator * (const node &x) const {
        node b;
        memset(b.a, 0x3f3f3f3f, sizeof b.a);
        for(int k = 1; k <= tot; k++)
            for(int i = 1; i <= tot ;i++)
                for(int j = 1; j <= tot ;j++)
                    b.a[i][j] = min(b.a[i][j], a[i][k] + x.a[k][j]);
        return b;
    }
}ans, dis;

int num[1000086];
signed main(){
    memset(dis.a, 0x3f3f3f3f, sizeof dis.a);
    n = read(), t = read(), s = read(), e = read();
    while(t--){
        int u = read(), v = read(), w = read();
        if(!num[v]) num[v] = ++tot;
        if(!num[w]) num[w] = ++tot;
        dis.a[num[v]][num[w]] = dis.a[num[w]][num[v]] = u;
    }
    n--;
    ans = dis;
    while(n){
        if(n & 1) ans = ans * dis;
        dis = dis * dis;
        n >>= 1;
    }
    cout << ans.a[num[s]][num[e]] << endl;
    return 0;
}
posted @ 2020-04-28 15:43  Gary_818  阅读(98)  评论(0编辑  收藏  举报