8月13日模拟赛_子节点 图论模拟赛总结,dfs+概率+线段树优化建图+差分约束
T1 \(Sign\)

题目

这是一道签到题

给出一棵\(N\)个节点的树,求所有七点为叶节点的有向路径,其上每一条边权值和的和

\(Input\)

第一行是一个整数\(N\)

接下来\(N-1\)行,每行三个整数\(L_i,A_i,B_i\),代表存在一条
连接\(A_i\)\(B_i\)的长度为\(L_i\)的边。

\(Output\)

输出一个整数,代表所求结果

题解

对于一个以\(x\)为根的树,用\(dfs\)序找到他的 子树大小(\(size\))和叶子节点个数(\(s\)),计算每条边的贡献。

如果是子树中的叶子节点向外走,贡献为:

\(s_x*(n-size_x)*dis\)

如果是子树外的叶子节点向里走,贡献为:

\((sum-s_x)*size_x*dis\)

其中,\(sum\)是总叶子节点个数

\(code\):

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+105;
int n,siz[N],sum,root,s[N],cnt,h[N<<1],de[N],tot,x,y,z,ans;
struct edge{int nex,to,v;}e[N<<1];
struct edge2{int fr,t,d;}a[N];
inline void add(int x,int y,int z){
	e[++cnt].to=y;e[cnt].v=z;
	e[cnt].nex=h[x];h[x]=cnt;
}
void dfs(int x,int f){
	siz[x]=1;
	if(de[x]==1) s[x]=1;
	for(int i=h[x];i;i=e[i].nex){
		int y=e[i].to;if(y==f) continue;
		a[++tot].fr=x;a[tot].t=y;a[tot].d=e[i].v;
		dfs(y,x);
		siz[x]+=siz[y];s[x]+=s[y];
	}
}
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}
signed main(){
	n=read();
	for(int i=1;i<n;i++){x=read();y=read();z=read();add(y,z,x);add(z,y,x);de[z]++;de[y]++;}
	for(int i=1;i<=n;i++)if(de[i]>1)root=i;else sum++;
	dfs(root,0);
	for(int i=1;i<n;i++){
		int k1=s[a[i].t]*(n-siz[a[i].t])*a[i].d;
		int k2=siz[a[i].t]*(sum-s[a[i].t])*a[i].d;
		ans+=k1+k2;
	}
	printf("%lld",ans);
	return 0;
}
T2 \(Map\)

题目

一张\(N\)个点的无向完全图,从\(1\)号点出发,每秒随机沿当前点的出度移动一条边。\(Q\)次询问,每次给出一个数\(t_i\),询问第\(t_i\)秒在\(1\)号点的概率,答案对\(998244353\)取模。

\(Input\)

第一行是两个整数\(N,Q\)

接下来\(Q\)行,每行一个整数,第\(i+1\)行的数字代表\(t_i\)

\(Output\)

输出\(Q\)行,每行一个非负整数,第\(i\)行的数字代表第\(i\)次询问的结果。

样例

\(Input\)

\(3\) \(2\)
\(0\)
\(2\)

\(Output\)

\(1\)
\(499122177\)

T3

此处

T4

座右铭:我从来没有见过这样阴郁而又光明的日子。