题目大意:
一张n个点m条边的无向图,边有边权w,从S出发,到T,每个时间店能走一步,求K时间点恰好到T所经过的边权的最小值。
同时有a个怪物
每个怪物有自己的游走路径,按照顺序在这些点直接游走,也是一个时间点移动一步。每个怪物游走的点个数2<=T<=4
求不碰到怪物的情况下,第一问的值
如果不可能输出impossible
C组数据
数据范围
k这么大一脸矩阵快速幂优化动态规划
我们考虑
fk,i,j
f
k
,
i
,
j
表示
i
i
到走
k
k
步经过的最小边权
k=1
k
=
1
时这就是原图的邻接矩阵
这里我们乘法需重新定义
(AB)i,j=min(max(Ai,k,Bk,j))
(
A
B
)
i
,
j
=
m
i
n
(
m
a
x
(
A
i
,
k
,
B
k
,
j
)
)
a=0
a
=
0
直接对邻接矩阵快速幂即可
有怪物的时候,我们就把所有到怪物所在点的边设为INF即可
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define rept(i,x) for(int i = linkk[x];i;i = e[i].n)
#define P pair<int,int>
const int INF = 1e9+7;
struct martix{
int a[60][60];
}G[13] , A , f;
int n , m , S , T;
ll k;
int num_mon , num_t[35] , att[35][5];
bool vis[60];
ll read()
{
ll sum = 0;char c = getchar();bool flag = true;
while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
if(!flag) sum = -sum;
return sum;
}
void re(martix &a)
{
rep(i,1,n)
rep(j,1,n)
a.a[i][j] = 0;
return;
}
martix mul(martix a,martix b)
{
martix ans;
rep(i,1,n)
rep(j,1,n)
{
ans.a[i][j] = INF;
rep(k,1,n)
ans.a[i][j] = min(ans.a[i][j] , max(a.a[i][k] , b.a[k][j]) );
}
return ans;
}
void mem(martix &a,martix b){rep(i,1,n)rep(j,1,n) a.a[i][j] = b.a[i][j];}
martix Pow(martix a,ll b)
{
martix ans;
mem(ans,a);
while(b)
{
if(b & 1) ans = mul(ans,a);
a = mul(a,a);
b >>= 1;
}
return ans;
}
void reset(martix &f){rep(i,1,n) rep(j,1,n) f.a[i][j] = INF;}
void init()
{
n = read();m = read();S = read();T = read();k = read();
reset(f);
rep(i,1,m)
{
int x = read() , y = read() , z = read();
f.a[x][y] = f.a[y][x] = min(z,f.a[x][y]);
}
num_mon = read();
rep(i,1,num_mon)
{
num_t[i] = read();
rep(j,1,num_t[i])
{
int tmp = j + num_t[i] - 1;
att[i][tmp%num_t[i]] = read();
}
}
rep(i,1,12)
{
mem(G[i>11?0:i],f);
memset(vis,0,sizeof(vis));
rep(k,1,num_mon){
if(!vis[att[k][i%num_t[k]]])
{
int x = att[k][i%num_t[k]];
vis[x] = true;
rep(j,1,n)
G[i>11?0:i].a[j][x] = INF;
}
}
}
mem(A,G[1]);
rep(i,2,12) A = mul(A,G[i>11?0:i]);
int tmp = k / 12;
if(tmp > 1) A = Pow(A,k/12-1);
else if(tmp == 0) A = G[1];
if(tmp != 0 && k % 12 != 0)A = mul(A,G[1]);
rep(i,2,k%12) A = mul(A,G[i]);
if(A.a[S][T] != INF) printf("%d\n",A.a[S][T]);
else printf("impossible\n");
return;
}
int main()
{
freopen("ishaac.in","r",stdin);
freopen("ishaac.out","w",stdout);
int tt = read();
while(tt--)
init();
return 0;
}