先 \(dp\) 出来不删任何边时的答案,然后考虑去掉一条边的影响。
去掉一条边 \((u,v)\),会使得流到 \(v\) 的流量减少,但流到 \(u\) 的流量不变,就相当于是减少 \(v\) 的流量,增加 \(u\) 其它终点的流量。
发现 增加/减少 流量可以转换为初始的时候管道就有 \(+x/-x\) 的污水,所以先处理出来初始有的污水,再来一次拓扑排序即可。
但这样还是 \(n^2\) 的,\(v\) 增加的污水可以转换到 \(u\) 增加的污水,这样就可做了。
#include<bits/stdc++.h> #define ri signed #define pd(i) ++i #define bq(i) --i #define func(x) std::function<x> namespace IO{ char buf[1<<21],*p1=buf,*p2=buf; #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++ #define debug1(x) std::cerr << #x"=" << x << ' ' #define debug2(x) std::cerr << #x"=" << x << std::endl #define Debug(x) assert(x) struct nanfeng_stream{ template<typename T>inline nanfeng_stream &operator>>(T &x) { bool f=false;x=0;char ch=gc(); while(!isdigit(ch)) f|=ch=='-',ch=gc(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc(); return x=f?-x:x,*this; } }cin; } using IO::cin; namespace nanfeng{ #define FI FILE *IN #define FO FILE *OUT template<typename T>inline T cmax(T x,T y) {return x>y?x:y;} template<typename T>inline T cmin(T x,T y) {return x>y?y:x;} using ll=long long; static const int N=2.5e5+7,MOD=998244353; struct edge{int v,nxt;}e[N<<1]; int first[N],deg[N],td[N],ot[N],a[N<<1],inv[N<<1],U[N<<1],V[N<<1],INV,t=1,n,m,r,k; ll dp[N],tdp[N],sum; std::queue<int> que; auto add=[](int u,int v) {e[t]={v,first[u]},first[u]=t++;}; auto fpow=[](ll x,int y) { ll res=1; while(y) { if (y&1) res=res*x%MOD; x=x*x%MOD; y>>=1; } return res; }; inline int main() { FI=freopen("water.in","r",stdin); FO=freopen("water.out","w",stdout); cin >> n >> m >> r >> k; for (ri i(1);i<=k;pd(i)) { cin >> U[i] >> V[i] >> a[i]; ++ot[U[i]],++deg[V[i]]; add(U[i],V[i]); sum+=a[i]; } sum%=MOD; INV=fpow(sum,MOD-2); inv[1]=1; for (ri i(2);i<=k;pd(i)) inv[i]=1ll*(MOD-MOD/i)*inv[MOD%i]%MOD; for (ri i(1);i<=m;pd(i)) que.push(i),dp[i]=1ll; memcpy(td+1,deg+1,sizeof(int)*n); while(!que.empty()) { int x=que.front(); que.pop(); const int iv=inv[ot[x]]; for (ri i(first[x]),v;i;i=e[i].nxt) { (dp[v=e[i].v]+=dp[x]*iv%MOD)%=MOD; --td[v]; if (!td[v]) que.push(v); } } for (ri i(1);i<=k;pd(i)) { const int u=U[i],v=V[i],iv=1ll*a[i]*INV%MOD; tdp[u]+=dp[u]*inv[ot[u]-1]%MOD*iv%MOD; tdp[v]-=dp[u]*inv[ot[u]-1]%MOD*iv%MOD; } for (ri i(1);i<=n;pd(i)) { dp[i]=tdp[i]%MOD; if (i<=m) dp[i]+=1ll,que.push(i); } while(!que.empty()) { int x=que.front(); que.pop(); const int iv=inv[ot[x]]; for (ri i(first[x]),v;i;i=e[i].nxt) { (dp[v=e[i].v]+=dp[x]*iv%MOD)%=MOD; --deg[v]; if (!deg[v]) que.push(v); } } for (ri i(n-r+1);i<=n;pd(i)) printf("%lld ",(dp[i]%MOD+MOD)%MOD); return 0; } } int main() {return nanfeng::main();}