Ciao, stavo provando a fare oii_smaltimento, ma fa solo 23/100. Riesce a fare i subtask 1-2-3-5 (Nel 4 fallisce l’ ultimo test) e tutto il resto va fuori memory limit. Per l’errore non ho idea di cosa sia, ma forse è un caso limite o una svista nel codice che si attiva solo in certi casi, mentre per il memory limit credo che la priority queue per qualche motivo si popoli di pair<cost, conn> per qualche motivo inutili (è l’unica struttura dati di dimensione variabile nel programma). Avete qualche suggerimento? Grazie mille!
Descrizione dell’algoritmo:
L’algoritmo è una sorta di Dijkstra/BFS dal nodo N(il “barile vuoto” che producono le trasformazioni che non producono niente) al nodo 0 (Il barile di OI_2) in un grafo in cui ogni processo di conversione è stato trasformato in un “fascio” di archi, che ho chiamato conn, e il verso di ogni conn è stato invertito.
L’idea è che un barile arrivato al nodo N ho costo 0 per essere smaltito, per cui tutti i tipi di barili che si possono trasformare in N richiedono 1. A questo punto ogni tipo di barile costa 1 + la somma dei costi di tutti i barili in cui viene trasformato.
#include<bits/stdc++.h>
using namespace std;
#define f first
#define s second
#define ll long long
#define llu long long unsigned
#define oo INT_MAX;
#define pb push_back
#define rb pop_back
#define d(x) //cerr << __LINE__ << ": " << #x << " = " << x << endl
typedef pair<int,int> ii;
typedef vector<int> vi;
typedef vector<vi> mi;
struct conn{
vi to; int from;
conn(vi to, int from): to(to), from(from){};
conn(){};
bool operator<(conn other) const{ return from < other.from; }
};
long long smaltisci(int N, int M, vector<int> A, vector<vector<int>> B) {
vector<vector<conn>> AL(N+1);
for(int p=0; p<M; p++){
if(B[p].empty()) B[p] = {N};
for(int t: B[p]){
AL[t].pb(conn(B[p], A[p]));
}
}
set<pair<int, conn>> frontiera = {};
for(conn c: AL[N]){
if(c.to.size()==1){
frontiera.insert({1, c});
}
}
vi cost(N+1, INT_MAX); cost[N] = 0;
vi FC(N+1, INT_MAX); cost[N] = 0;
conn curr; int cc;
while(cost[0] == INT_MAX){
curr=frontiera.begin() -> s;
cc=frontiera.begin() -> f;
frontiera.erase(frontiera.begin());
if(cost[curr.from] == INT_MAX) cost[curr.from] = cc;
else continue;
for(conn c: AL[curr.from]){
if(cost[c.from] != INT_MAX) continue;
int val = 1;
for(int t: c.to) if(cost[t] == INT_MAX or t == 0){
val = 0;
break;
}else val += cost[t];
if(val and val<FC[c.from]){
frontiera.insert({val, c});
if(FC[c.from] != INT_MAX) frontiera.erase(frontiera.lower_bound({FC[c.from], c}), frontiera.upper_bound({FC[c.from], c}));
FC[c.from] = val;
}
}
}
return cost[0];
}