Pagini recente »
Rating alexandru radita (alexradita2)
|
Istoria paginii runda/2024-03-10-clasa-5-concurs05/clasament
|
Clasament 9c_tema10
|
2023-09-24-clasa-8-tema-2
|
Cod sursă (job #816413)
Cod sursă (job
#816413)
// Metodă: Generăm componentele tare conexe cu algoritmul lui Kosaraju. Acesta
// le emite în ordine topologică. Apoi rulăm o programare dinamică înainte:
// din fiecare nod accesibil din hotel, propagăm profitul la dreapta.
#include <stdio.h>
#include <vector>
const int MAX_NODES = 100'000;
struct node {
std::vector<int> adj, adjt;
int comp;
short cost;
bool mark;
};
struct component {
std::vector<int> adj;
int incoming, profit;
bool reachable_from_h;
};
node nd[MAX_NODES + 1];
component scc[MAX_NODES + 1];
int order[MAX_NODES];
int n, hotel, num_scc;
void read_graph() {
FILE* f = fopen("risipa.in", "r");
int m, u, v;
fscanf(f, "%d %d %d", &n, &m, &hotel);
for (u = 1; u <= n; u++) {
fscanf(f, "%hd", &nd[u].cost);
}
while (m--) {
fscanf(f, "%d %d", &u, &v);
nd[u].adj.push_back(v);
nd[v].adjt.push_back(u);
}
fclose(f);
}
void dfs(int u) {
nd[u].mark = true;
for (auto v: nd[u].adj) {
if (!nd[v].mark) {
dfs(v);
}
}
static int time_out = 0;
order[time_out++] = u;
}
// DFS #1: Colectează nodurile în ordinea timpilor de ieșire.
void dfs_driver() {
for (int u = 1; u <= n; u++) {
if (!nd[u].mark) {
dfs(u);
}
}
}
void tdfs(int u) {
nd[u].mark = false;
nd[u].comp = num_scc;
scc[num_scc].profit += nd[u].cost;
for (auto v: nd[u].adjt) {
if (nd[v].mark) {
tdfs(v);
}
}
}
// DFS #2 pe graful de mai sus în ordinea descrescătoare a timpilor de ieșire.
void transpose_dfs_driver() {
for (int i = n - 1; i >= 0; i--) {
int u = order[i];
if (nd[u].mark) {
tdfs(u);
num_scc++;
}
}
}
void build_scc_graph() {
for (int u = 1; u <= n; u++) {
for (int v: nd[u].adj) {
int cu = nd[u].comp, cv = nd[v].comp;
if (cu != cv) {
scc[cu].adj.push_back(cv);
}
}
}
}
void compute_scc_profits() {
scc[nd[hotel].comp].reachable_from_h = true;
for (int i = 0; i < num_scc; i++) {
if (scc[i].reachable_from_h) {
scc[i].profit += scc[i].incoming;
for (int j: scc[i].adj) {
scc[j].reachable_from_h = true;
scc[j].incoming = std::max(scc[j].incoming, scc[i].profit);
}
} else {
scc[i].profit = 0;
}
}
}
void write_answers() {
FILE* f = fopen("risipa.out", "w");
for (int u = 1; u <= n; u++) {
fprintf(f, "%d\n", scc[nd[u].comp].profit);
}
fclose(f);
}
int main() {
read_graph();
dfs_driver();
transpose_dfs_driver();
build_scc_graph();
compute_scc_profits();
write_answers();
return 0;
}