効果の対象に
需要がある\(m個\)は、点、接続グラフを無向エッジ\(S \)ポイント\(T \)を介して\(K \)のエッジの最短(\(1 \のLeq M \のLeq 100 \)、\ (1 \のLeq K \ 1当量6〜10 ^ \) )。
問題の解決策
エッジの数\(m個\)は小さく、はっきりポイント(\ N-)\もより、非常に小さくない(200 \)\、我々は最初に離散化することができます。
我々が得ることができる(\ N-)\前記マトリックス、ポイント間の隣接行列を\([I] [J ] \) に相当する点\(Iは\)ポイント\(J \)を介して\ (1 \)の最短エッジ。
このケースでは、設定(DP [I]、[J \を 〕〔K '] \) ポイントを表し\(Iは\)ポイント\(J \)を介して(\ \ K)'最短辺明らかである
\ [DP [i]が[j]が
[1] = [I] [J] \] と
\ [DP [I] [J ] [K '] = \ \ {DP分[I] [L] [K' - 1] + DP [L]
[J] [K ' - 1] \}、K'> 1 \] 明らかに、DPの単純な複雑\(O(KN ^ 2)\)。
このプロセスは、$ O(N ^ 2 \ログ滴の複雑されるように多くのマトリックス乗算、同じように、我々はまた、迅速に電力を最適化するためにマトリクスを使用することができ、実際に観察される {K})が$ 。
#include <iostream>
#include <cstring>
#include <algorithm>
#define MAX_M (100 + 5)
using namespace std;
int K, m, s, t;
int u[MAX_M], v[MAX_M];
long long w[MAX_M];
int tmp[MAX_M << 1];
int to[1000005], n;
struct Matrix
{
long long mat[MAX_M][MAX_M];
Matrix()
{
memset(mat, 0x3f, sizeof mat);
return;
}
friend Matrix operator * (Matrix a, Matrix b)
{
Matrix c;
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= n; ++j)
{
for(int k = 1; k <= n; ++k)
{
c.mat[i][j] = min(c.mat[i][j], a.mat[i][k] + b.mat[k][j]);
}
}
}
return c;
}
friend Matrix operator *= (Matrix & a, Matrix b)
{
return a = a * b;
}
};
Matrix a;
int main()
{
cin >> K >> m >> s >> t;
for(int i = 1; i <= m; ++i)
{
cin >> w[i] >> u[i] >> v[i];
tmp[i << 1 ^ 1] = u[i];
tmp[i << 1] = v[i];
}
sort(tmp + 1, tmp + m + m + 1);
for(int i = 1; i <= (m << 1); ++i)
{
if(tmp[i] != tmp[i - 1]) to[tmp[i]] = ++n;
}
for(int i = 1; i <= m; ++i)
{
u[i] = to[u[i]];
v[i] = to[v[i]];
a.mat[u[i]][v[i]] = min(a.mat[u[i]][v[i]], w[i]);
a.mat[v[i]][u[i]] = min(a.mat[v[i]][u[i]], w[i]);
}
--K;
Matrix res = a;
while(K)
{
if(K & 1) res *= a;
a *= a;
K >>= 1;
}
cout << res.mat[to[s]][to[t]];
return 0;
}