SCOI2019 RGB

RGB

En un árbol con puntos \ (N \) , cada punto tiene su propio color (rojo, verde o azul), y cada lado tiene su propia longitud.

Su tarea es contar el número de pares de conjuntos de puntos \ ((U, V) \) , satisfaciendo:

  1. Los puntos en el conjunto \ (U \) son todos rojos o verdes, y los puntos en el conjunto \ (V \) son todos verdes o azules;

  2. El conjunto \ (U \) y el conjunto \ (V \) están conectados (si algún punto en una ruta simple entre dos puntos en el conjunto pertenece al conjunto, se dice que el conjunto está conectado);

  3. Hay un ambos pertenecientes al conjunto \ (el U- \) y perteneciente al conjunto \ (V \) punto \ (X \) , tal que para cualquiera perteneciente al conjunto \ (el U- \) o un conjunto de \ (V \) punto \ (Y \ ) , Satisfaga la distancia entre el punto \ (x \) y el punto \ (y \) no más de \ (M \) (la distancia entre dos puntos es la suma de las longitudes de los bordes en el camino simple entre ellos).

La respuesta es módulo \ (10 ​​^ 9 + 7 \) .

Para todos los puntos de datos, \ (N≤2000 \) .

Solución

https://blog.csdn.net/sslz_fsy/article/details/101315047

Considere el caso donde solo hay un punto verde, es decir, un árbol desnudo DP, seleccionando por la fuerza el punto actual

\ [f_R (u) = \ prod (f_R (v) +1) \\ f_B (u) = \ prod (f_B (v) +1) \\ ans = f_R (u) f_B (u) \]

Podemos enumerar todos los puntos verdes y contar las respuestas nuevamente, considerando qué situaciones se considerarán pesadas.

Si los puntos verdes no están conectados, obviamente no será pesado, solo cuando los puntos verdes se junten.

Queremos que la contribución de los puntos de Yituo cuente solo una vez y encuentre \ (puntos-bordes = 1 \)

Por lo tanto, puede enumerar cada punto verde y restar la contribución de cada borde para hacer que un bloque conectado cuente solo una vez.

Complejidad de tiempo \ (O (N ^ 2) \) .

CO int N=2e3+10;
int W;
char col[N];
struct edge {int u,v,w;} E[N];
vector<edge> to[N];
int fR[N],fB[N],ans;

void dfs(int u,int fa,int dis){
	if(dis>W) {fR[u]=fB[u]=0; return;}
	if(col[u]!='R') fB[u]=1;
	if(col[u]!='B') fR[u]=1;
	for(int i=0;i<(int)to[u].size();++i){
		int v=to[u][i].v;
		if(v==fa) continue;
		dfs(v,u,dis+to[u][i].w);
		fB[u]=mul(fB[u],fB[v]+1);
		fR[u]=mul(fR[u],fR[v]+1);
	}
}
IN void insert(int u){
	dfs(u,0,0);
	ans=add(ans,mul(fR[u],fB[u]));
}
IN void erase(int u,int v,int w){
	dfs(u,v,w),dfs(v,u,w);
	ans=add(ans,mod-mul(mul(fR[u],fB[u]),mul(fR[v],fB[v])));
}
int main(){
	freopen("RGB.in","r",stdin),freopen("RGB.out","w",stdout);
	int n=read<int>();read(W);
	scanf("%s",col+1);
	for(int i=1;i<n;++i){
		int u=read<int>(),v=read<int>(),w=read<int>();
		E[i]=(edge){u,v,w};
		to[u].push_back((edge){u,v,w}),to[v].push_back((edge){v,u,w});
	}
	for(int i=1;i<=n;++i)if(col[i]=='G') insert(i);
	for(int i=1;i<n;++i)if(col[E[i].u]=='G' and col[E[i].v]=='G') erase(E[i].u,E[i].v,E[i].w);
	printf("%d\n",ans);
	return 0;
}

Supongo que te gusta

Origin www.cnblogs.com/autoint/p/12685723.html
Recomendado
Clasificación