题解。
假如设
Fi
F
i
表示从i走到终点的答案,那么对于不同的时间,难以将参数T分离。
于是,假如我们可以计算
Gi
G
i
表示点i的期望经过次数,一条边(x,y)的贡献就是
Gx⋅P(x,y)⋅Len
G
x
⋅
P
(
x
,
y
)
⋅
L
e
n
,那么就可以根据边的p分成两部分,统计左右的一次项系数与常数就可以了。
对于每一个起点,发现计算
Gi
G
i
的过程都是类似的,唯一不同的是起点S
G
G
的方程中要加一。
再设,若S是起点则
Cs=1
C
s
=
1
否则
Cs=0
C
s
=
0
,通过高斯消元解出
Gi=∑ai⋅Ci
G
i
=
∑
a
i
⋅
C
i
。
接下来就是离线询问,简单统计了。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define abs(x) ((x)>0?(x):-(x))
using namespace std;
typedef long long ll;
const ll mo = 1e9 + 7, N = 410, M = 1e5+10;
ll f[N][2*N],n,m,q;
ll wsum[N],inv[N];
ll T,X;
ll bz[N],sg[N];
pair<int,pair<int,int> > qu[2000100];
ll ksm(ll x,ll y) {
ll ret = 1; for (;y;y>>=1) {
if (y & 1) ret = ret * x % mo;
x = x * x % mo;
} return ret;
}
struct edge{
ll x,y,S,C,P,Po;
bool operator < (const edge &b) const{
return P < b.P;
}
} e[M];
void gauss() {
for (int i = 1; i <= n; i++) f[i][i] = -1, f[i][i+n] = 1;
for (int i = 1; i <= m; i++) {
int x = e[i].x, y = e[i].y;
f[y][x] = (f[y][x] + e[i].Po) % mo;
}
for (int i = 1; i <= n; i++) {
int fd = 0; for (int j = 1; j <= n; j++)
if (!bz[j] && f[j][i]) {
sg[i] = j, bz[j] = 1, fd = j; break;
}
for (int j = 1; j <= n; j++) if (!bz[j] && f[j][i]) {
ll a = f[fd][i],b = f[j][i];
for (int z = 0; z <= 2 * n; z++)
f[j][z] = (f[j][z] * a - f[fd][z] * b) % mo;
}
}
for (int i = n; i; i--) {
int fd = sg[i], inv = ksm(f[fd][i],mo-2);
f[fd][i] = f[fd][i] * inv % mo;
for (int j = n+1; j <= n*2; j++)
f[fd][j] = f[fd][j] * inv % mo;
for (int j = 1; j <= n; j++) if (j != i && f[j][i]) {
int xs = f[j][i];
for (int z = n + 1; z <= 2 * n; z++) {
f[j][z] = (f[j][z] - f[fd][z] * xs) % mo;
}
}
for (int j = n+1; j <= n*2; j++)
f[fd][j] = - f[fd][j];
}
}
ll ans[2000100];
ll sL[N][2],sR[N][2];
int main() {
freopen("dream.in","r",stdin);
// freopen("dream.out","w",stdout);
cin>>n>>m>>q;
for (ll i = 1; i <= m; i++) {
ll u,v,w,s,c,p;
scanf("%lld %lld %lld %lld %lld %lld",
&e[i].x,&e[i].y,&e[i].Po,&e[i].S,&e[i].C,&e[i].P);
wsum[e[i].x] = (wsum[e[i].x] + e[i].Po)%mo;
if (e[i].x==n) i--,m--;
}
for (ll i = 1; i <= n; i++)
inv[i] = ksm(wsum[i],mo-2);
for (int i = 1; i <= m; i++)
e[i].Po = e[i].Po * inv[e[i].x] % mo;
sort(e+1,e+1+m);
for (int i = 1; i <= q; i++) {
scanf("%d %d",&qu[i].first,&qu[i].second.first);
qu[i].second.second = i;
}
sort(qu+1,qu+1+q);
gauss();
int d = 0;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) if (f[e[i].x][j+n]) {
int xs=f[e[i].x][j+n];
sR[j][1] = (sR[j][1] - xs * e[i].Po % mo * e[i].S) % mo;
sR[j][0] = (sR[j][0] + xs * e[i].Po % mo * (e[i].S * e[i].P % mo + e[i].C)) % mo;
}
}
for (int i = 1; i <= q; i++) {
while (d < m && e[d+1].P <= qu[i].first) {
d++;
for (int j = 1; j <= n; j++) if (f[e[d].x][j+n]) {
int xs=f[e[d].x][j+n];
sR[j][1] = (sR[j][1] + xs * e[d].Po % mo * e[d].S) % mo;
sR[j][0] = (sR[j][0] - xs * e[d].Po % mo * (e[d].S * e[d].P % mo + e[d].C)) % mo;
sL[j][1] = (sL[j][1] + xs * e[d].Po % mo * e[d].S) % mo;
sL[j][0] = (sL[j][0] + xs * e[d].Po % mo * (e[d].C - e[d].S * e[d].P % mo)) % mo;
}
}
int X = qu[i].second.first;
ans[qu[i].second.second] = (sL[X][0] + sR[X][0] + qu[i].first * (sL[X][1] + sR[X][1])) % mo;
}
for (int i = 1; i <= q; i++) printf("%lld\n",(ans[i]+mo)%mo);
}