2022.10.5 总结

A

初始时只有 \(a_k=1\),有 \(m\) 次操作,每次交换 \(a_u,a_v\) 的值,问忽略多少次操作可以使最终 \(a_i=1\).
简单DP即可。

code
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=1e5+10,inf=2e9;
int n,m,k,a[N],b[N],dp[N];
int main() {
	scanf("%d%d%d",&n,&k,&m);
	for(int i=1; i<=m; i++) scanf("%d%d",&a[i],&b[i]);
	if(m==0) {
		for(int i=1; i<=n; i++) 
			if(i==k) printf("0 ");
			else printf("-1 ");
		return 0;
	}
	for(int i=1; i<=n; i++) dp[i]=inf;
	dp[k]=0; 
	for(int i=1; i<=m; i++) {
		int x=a[i],y=b[i];
		if(x==y) continue;
		int t=dp[x];
		dp[x]=min(dp[x]+1,dp[y]);
		dp[y]=min(dp[y]+1,t);
	}
	for(int i=1; i<=n; i++) printf("%d ",dp[i]>=inf?-1:dp[i]);
	return 0;
}

B

问树的每条边分别删去(询问独立),剩下两个部分每个部分中连通块的数量。
换根DP即可。
原始方程,\(u\) 为子树根,\(v\) 为儿子时: \(s_u=\prod (1+s_v)\),表示 \(u\) 为子树根下的包含 \(u\) 的连通块个数。
换根方程,\(u\) 为总树根,\(f\) 为父亲时:\(dp_u=s_u*(\dfrac{dp_f}{1+s_u}+1)\) ,表示 \(u\) 为整棵树根时包含 \(u\) 的连通块个数。

code

#include<algorithm>
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;
const LL N=5e5+10,mod=998244353;
LL n,tot,head[N],ver[2*N],nxt[2*N],fu[N],fv[N];
LL s[N],depth[N],dp[N],sum[N];
void addedge(LL x,LL y) {
	ver[++tot]=y;
	nxt[tot]=head[x];
	head[x]=tot;
}
void DFS(LL u,LL father) {
	s[u]=1;
	depth[u]=depth[father]+1;
	for(LL i=head[u]; i; i=nxt[i]) {
		LL v=ver[i];
		if(v==father) continue;
		DFS(v,u);
		s[u]=s[u]*(1+s[v])%mod;
		sum[u]+=sum[v];
	}
	sum[u]=(sum[u]+s[u])%mod;
}
LL exgcd(LL a,LL b,LL &x,LL &y) {
	if(b==0) {x=1; y=0; return a;}
	LL g=exgcd(b,a%b,x,y),z=x;
	x=y; y=z-(a/b)*x;
	return g;
}
LL f(LL a,LL b) {
	LL d,y;
	exgcd(b,mod,d,y);
	return (a*d%mod+mod)%mod;
}
void dfs2(LL u,LL father) {
	if(u!=1) dp[u]=s[u]*(f(dp[father],s[u]+1)+1)%mod;
	else dp[u]=s[u];
	for(LL i=head[u]; i; i=nxt[i]) {
		LL v=ver[i];
		if(v==father) continue;
		dfs2(v,u);
	}
}
signed main() {
	scanf("%lld",&n);
	for(LL i=1; i<n; i++) {
		scanf("%lld%lld",&fu[i],&fv[i]);
		addedge(fu[i],fv[i]);
		addedge(fv[i],fu[i]);
	}
	DFS(1,1);
	dfs2(1,1);
	for(LL i=1; i<n; i++) {
		LL u=fu[i],v=fv[i];
		if(depth[u]>depth[v]) {
			printf("%lld %lld\n",sum[u]%mod,(sum[1]-sum[u]-(dp[v]-f(dp[v],s[u]+1))+10000*mod)%mod);
		} else {
			printf("%lld %lld\n",(sum[1]-sum[v]-(dp[u]-f(dp[u],s[v]+1))+10000*mod)%mod,sum[v]%mod);
		}
	}
	return 0;
}

posted @ 2022-10-05 16:23  s1monG  阅读(33)  评论(0)    收藏  举报