其他分享
首页 > 其他分享> > Poj 3613 Cow Relays (图论)

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] + 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;
}

标签:ch,int,松弛,3613,Poj,条边,include,Relays
来源: https://www.cnblogs.com/rui-4825/p/12794722.html