El Concurso Regional de Shanghai de Asia ICPC 2019 (repetición) M-Blood Pressure Game (flujo de costos y contribución de cálculo)

Enlace: https://ac.nowcoder.com/acm/contest/4370/M
Fuente: Niuke
 

Descripción del Título

1Gugulu, un JBer, que fue ACMer hace un año, vuelve a la Universidad de Shanghai para participar en el Concurso Internacional de Programación Universitaria. Sin embargo, cada vez que Gugulu venía a la Universidad de Shanghai, siempre obtenía una Medalla de Hierro y consideraba esta competencia como una JB. Para aliviar su dolor, Gugulu iría al Parque Disneyland de Shanghai para divertirse tomando la montaña rusa. A Gugulu le encanta tanto la sensación de presión arterial alta que lo hace sentir como un pájaro feliz que olvida todas las respuestas incorrectas y el límite de tiempo excedido, etc.

Podemos considerar la trayectoria de la montaña rusa como una lista de puntos de inflexión con diferentes alturas que se pueden representar como una matriz {a1, a2, a3,…, an} \ {a_1, a_2, a_3,…, a_n \} { a1, a2, a3,…, an} de tamaño n {n} n, y la presión arterial final de Gugulu después del juego de la montaña rusa se cuenta como la suma de todos los valores absolutos de las diferencias entre los n− 1 {n - 1} n − 1 pares de números de matriz adyacentes, es decir, ∑i = 1n − 1∣ai − ai + 1∣ \ displaystyle \ sum_ {i = 1} ^ {n-1} \ left | a_i - a_ {i + 1} \ right | i = 1∑n − 1 ∣ai −ai + 1 ∣.

Gugulu siempre recibió medallas de hierro y siempre recibe medallas de hierro, lo que lo hace seguir tomando la montaña rusa una y otra vez. Sin embargo, a medida que juega más juegos, su umbral en el valor de la presión arterial que puede hacerlo feliz sigue aumentando. Como resultado, la montaña rusa del parque Disneyland de Shanghai ya casi no puede satisfacer las necesidades de Gugulu.

Por lo tanto, Gugulu decide agregar un conjunto de m puntos de inflexión adicionales en cualquier orden en esta ruta; sin embargo, para considerar la realidad en la distancia de la ruta original, puede agregar como máximo un punto de inflexión en cualquier posición original entre dos elementos originales en la matriz (y como máximo uno en la cabeza, como máximo uno en la cola). Gugulu quiere hacer que su presión arterial sea lo más alta posible, y quiere saber cuánto puede alcanzar su sangre como máximo cuando ha agregado {1,2,3,…, m} {\ {1, 2, 3,… , m \}} {1,2,3,…, m} nextra Roller Coaster girando puntos en el camino.

Usted, otro JBer, está seguro de que Gugulu es lo suficientemente inteligente como para obtener la presión arterial más alta posible. Es muy importante que calcule los números exactos para programar una cita con un cardiólogo adecuado con anticipación para salvar la vida de Gugulu. ¡Debes resolver este problema! ¡La presión arterial de Gugulu está fuera de control!

Ingrese descripción:

La primera línea de la entrada da el número de casos de prueba, T \ mathbf {T} T (1≤T≤10001 \ leq \ mathbf {T} \ leq 10001≤T≤1000). T \ mathbf {T} T siguen casos de prueba. 
Para cada caso de prueba, la primera línea contiene dos números enteros, n {n} n (1≤n≤6001 \ leq n \ leq 6001≤n≤600) y m {m} m (1≤m≤n + 11 \ leq m \ leq n + 11≤m≤n + 1)  
Luego, en la segunda línea, hay n {n} n enteros {a1, a2, a3,…, an} \ {a_1, a_2, a_3,…, a_n \ } {a1, a2, a3,…, an} (1≤ai≤109) (1 \ leq a_i \ leq 10 ^ 9) (1≤ai ≤109), que denota n {n} n Puntos de inflexión originales de la montaña rusa. Luego, en la tercera línea, hay m {m} m enteros {b1, b2, b3,…, bm} \ {b_1, b_2, b_3,…, b_m \} {b1, b2, b3,… , bm} (1≤bi≤109) (1 \ leq b_i \ leq 10 ^ 9) (1≤bi ≤109), que denota los m {m} m de puntos de inflexión de la montaña rusa que se agregarán.
Como se trata de una emocionante montaña rusa, se garantiza que todos los n + m {n + m} n + m enteros en las dos matrices son diferentes por pares. 
Hay como máximo 10 {10} 10 casos de prueba cuyo n {n} n es más de 100 {100} 100.

Descripción de salida:

Para cada caso de prueba, genere tres líneas. La primera línea contiene "Case #x:", donde x {x} x es el número de caso de prueba (comenzando desde 1 {1} 1). En la segunda línea, debe haber m {m} m enteros que representen cuánto podría alcanzar la presión arterial de Gugulu si hubiera agregado {1, 2, 3,…, m} puntos de giro extra en la montaña rusa en el camino. En la tercera línea, debe haber n + m {n + m} n + m enteros que representan las alturas de la ruta final de la montaña rusa si ha agregado todos los m {m} m puntos de inflexión adicionales. Si hay varias soluciones, imprima cualquiera de ellas.

Ejemplo 1

entrar

Copiar 6 2 3 5 11 10 3 1 4 1 1 2 3 4 5 4 2 1 2 3 4 5 6 4 5 1 2 3 4 5 6 7 8 9 4 4 10 50 3 6 1 9 23 5 4 2 10 50 3 6 9 23

6 
2 3 
5 11 
10 3 1 
4 1 
1 2 3 4 
5 
4 2 
1 2 3 4 
5 6 
4 5 
1 2 3 4 
5 6 7 8 9 
4 4 
10 50 3 6 
1 9 23 5 
4 2 
10 50 3 6 
9 23

Salida

复制 Caso # 1:16 22 27 10 5 1 11 3 Caso # 2: 9 1 5 2 3 4 Caso # 3:11 15 1 6 2 5 3 4 Caso # 4:17 27 33 38 39 5 1 9 2 8 3 7 4 6 Caso # 5: 124 142147150 5 10 1 50 3 23 6 9 Caso # 6: 124 127 10 50 3 23 6 9

Caso # 
1:16 22 27 
10 5 1 11 3 
Caso # 2: 
9 
1 5 2 3 4 
Caso # 
3:11 15 
1 6 2 5 3 4 
Caso # 
4:17 27 33 38 39 
5 1 9 2 8 3 7 4 6 
Caso # 5: 
124142147150 
5 10 1 50 3 23 6 9 
Caso # 6: 
124 127 
10 50 3 23 6 9

Idea principal:

Darle una secuencia de longitud N y una secuencia de longitud M. Necesita insertar estos números M en la primera secuencia. Solo se puede insertar un número entre los dos números (se puede colocar a la izquierda o derecha) , El orden de inserción es arbitrario y el peso de la secuencia es la suma del valor absoluto de la diferencia entre números adyacentes. Imprima los números M en la primera fila, el i-ésimo número representa el valor de peso máximo después de insertar los números i, y la segunda línea muestra la secuencia del valor de peso máximo después de insertar los números M.

solución:

Hay N + 1 puntos que se pueden conectar a M números, correspondientes a N + 1 posiciones que se pueden insertar. Primero, calcule el peso de la secuencia inicial. Cuando se inserta un punto, su contribución es el peso después de la inserción-el original Peso, por lo que el método de mapeo es: el punto de origen está conectado a M puntos, el flujo es 1, el costo es 0, los M puntos están conectados a N + 1 puntos, el flujo es 1, el costo es la contribución y N + 1 puntos están conectados al sumidero Punto, el flujo es 1, el costo es 0, y el flujo de costo máximo se ejecuta M veces, y finalmente la secuencia se genera en la red residual.

Esta pregunta fue emitida por un equipo de los grandes de nuestra escuela (bajo la premisa de saber que es un flujo de red), y todas las ideas se aprenden de él, todavía soy demasiado bueno QAQ

 Código aceptado

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;

#define sc scanf
#define ls rt << 1
#define rs ls | 1
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define pir pair <int, int>
#define MK(x, y) make_pair(x, y)
#define MEM(x, b) memset(x, b, sizeof(x))
#define MPY(x, b) memcpy(x, b, sizeof(x))
#define lowbit(x) ((x) & -(x))
#define P2(x) ((x) * (x))

typedef long long ll;
const int Mod = 1e9 + 7;
const int N = 1210;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
inline ll dpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % Mod; b >>= 1; t = (t*t) % Mod; }return r; }
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t); b >>= 1; t = (t*t); }return r; }

struct Edge
{
	ll f, w;
	int r, v;
};
vector <Edge> G[N];
ll dis[N], flow[N];
ll mxflow, mxcost;
int n, m, sp, tp;
int pre[N], lst[N];
bool vis[N];
int a[N], b[N];

void Init() {
	sp = 0, tp = n + m + 2;
	for (int i = sp; i <= tp; i++)
		G[i].clear();
	mxflow = mxcost = 0;
}
void Add(int u, int v, ll f, ll w) {
	G[u].push_back({ f, w, SZ(G[v]), v });
	G[v].push_back({ 0, -w, SZ(G[u]) - 1, u });
}
bool Spfa() {   // 找到一条长短路的增广
	queue <int> q;
	for (int i = sp; i <= tp; i++) {
		dis[i] = -LINF;
		flow[i] = LINF;
		vis[i] = false;
	}
	q.push(sp);
	vis[sp] = true;
	dis[sp] = 0, pre[tp] = -1;

	while (!q.empty()) {
		int u = q.front();
		q.pop();
		vis[u] = false;

		for (int i = 0; i < SZ(G[u]); i++) {
			ll f = G[u][i].f, w = G[u][i].w;
			int v = G[u][i].v;
			if (f && dis[v] < dis[u] + w) {
				dis[v] = dis[u] + w;
				pre[v] = u;       // 前驱点
				lst[v] = i;       // 当前边的vector下标
				flow[v] = min(flow[u], f);
				if (!vis[v]) {
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	return pre[tp] != -1;
}

int main()
{
	int T;
	cin >> T;
	for (int Case = 1; Case <= T; Case++) {
		sc("%d %d", &n, &m);
		Init();

		ll ans = 0;
		for (int i = 1; i <= n; i++) {
			sc("%d", &a[i]);
			if (i > 1)
				ans += abs(a[i] - a[i - 1]);
		}

		// 源点->待插入点
		for (int i = 1; i <= m; i++) {
			sc("%d", &b[i]);
			Add(sp, i, 1, 0);
		}

		// 待插入点对原序列的贡献
		for (int i = 1; i <= m; i++) {
			for (int j = 1; j <= n + 1; j++) {
				ll w;
				if (j == 1)
					w = abs(b[i] - a[1]);
				else if (j == n + 1)
					w = abs(b[i] - a[n]);
				else
					w = abs(b[i] - a[j - 1]) + abs(b[i] - a[j]) - abs(a[j] - a[j - 1]);
				// 待插入->原序列
				Add(i, m + j, 1, w);
			}
		}

		// 原序列->汇点
		for (int i = 1; i <= n + 1; i++)
			Add(m + i, tp, 1, 0);

		printf("Case #%d:\n", Case);
		for (int i = 1; i <= m; i++) {
			Spfa();
			int now = tp;
			mxflow = flow[tp];
			mxcost = flow[tp] * dis[tp];
			while (now != sp) {
				G[pre[now]][lst[now]].f -= mxflow;
				G[now][G[pre[now]][lst[now]].r].f += mxflow;
				now = pre[now];
			}
			ans += mxcost;
			printf("%lld ", ans);
		}
		puts("");


		for (int i = m + 1; i <= n + m + 1; i++) {
			for (auto it : G[i]) {
				int v = it.v;
				if (v >= 1 && v <= m && it.f) {
					printf("%d ", b[v]);
					break;
				}
			}
			if (i == n + m + 1)
				puts("");
			else
				printf("%d ", a[i - m]);
		}
	}
	return 0;  // 改数组大小!!!用pair记得改宏定义!!!
}

 

Supongo que te gusta

Origin blog.csdn.net/weixin_43851525/article/details/107606512
Recomendado
Clasificación