2025_5_30 T4
Evan_Leo_Azir · · 题解
省选对我们来讲还是太过棘手了些,所以来补CSP-S放松放松
大概有CF2300 左右 中位蓝
首先,题目给出一个DAG,第一联想为
我们枚举那个“损坏”的边,每次都跑一遍上述的
想枚举损坏的边,肯定超时,我们考虑把所有可能坏掉的边的情况放在
先思考一下,对于一个点
假设坏水管连接的点为
对于
对于
设
显然,影响是
掌握此式子,我们先求出在没有炸水管的情况下每个点的期望流量,再对于每个点,枚举它炸掉的出边即可转移,但对于菊花图,此做法会被卡到
再思考一下,我们运用类似差分的思想,先利用
对于上文所述的
同样,在此情况下,其他的点
(
时间复杂度
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10,maxk=5e5+10,Mod=998244353;
int n,m,r,k,sumw,invs,cnte;
int head[maxn],in[maxn],in2[maxn],out[maxn],f[maxn],g[maxn];
struct EDGE{
int v,nxt,w;
}e[maxk];
queue<int>Q;
int qpow(int x,int y)
{
int ret=1;
while(y)
{
if(y&1) ret=1ll*ret*x%Mod;
x=1ll*x*x%Mod;
y>>=1;
}
return ret;
}
void adde(int u,int v,int w)
{
e[cnte]=(EDGE){v,head[u],w};
head[u]=cnte++;
}
int add(int x,int y) {return x+y>=Mod?x+y-Mod:x+y;}
int fadd(int x,int y) {return x-y>=0?x-y:x-y+Mod;}
int read()
{
int ret=0,w=1;char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {ret=(ret<<3)+(ret<<1)+(ch^48);ch=getchar();}
return ret*w;
}
void inpu()
{
n=read(),m=read(),r=read(),k=read();
memset(head,-1,sizeof(head));
for(int i=1,u,v,w;i<=k;i++)
{
out[u=read()]++,in[v=read()]++,sumw=add(sumw,w=read());
adde(u,v,w);
}
}
void pre()
{
for(int i=1;i<=n;i++) in2[i]=in[i];
for(int i=1;i<=m;i++) f[i]=g[i]=1;
invs=qpow(sumw,Mod-2);
}
void topo()
{
for(int i=1;i<=m;i++) Q.push(i);
while(!Q.empty())
{
int u=Q.front(),x=1ll*f[u]*qpow(out[u],Mod-2)%Mod;Q.pop();
for(int i=head[u],to;i!=-1;i=e[i].nxt)
{
if(!(--in[to=e[i].v])) Q.push(to);
f[to]=add(f[to],x);
}
}
}
void deal()
{
for(int i=1;i<=n;i++) in[i]=in2[i];
for(int u=1,p,q;u<=n-r;u++)
{
p=1ll*f[u]*qpow(out[u],Mod-2)%Mod,q=1ll*f[u]*qpow(out[u]-1,Mod-2)%Mod;
for(int i=head[u],to,w;i!=-1;i=e[i].nxt)
{
to=e[i].v,w=1ll*e[i].w*invs%Mod;
g[u]=add(g[u],1ll*out[u]*fadd(q,p)%Mod*w%Mod),g[to]=fadd(g[to],1ll*q*w%Mod);
}
}
for(int i=1;i<=n;i++) f[i]=g[i];
}
void solve()
{
inpu();
pre();
topo();
deal();
topo();
for(int i=n-r+1;i<=n;i++) printf("%d ",f[i]);
}
int main()
{
int t=1;
while(t--) solve();
return 0;
}