Cześć,
Rozwiązuję to zadanie:
https://szkopul.edu.pl/problemset/problem/pXcijJbDyC_jRAjkoxBH9sCO/site/?key=statement
Jestem na etapie pierwszym, czyli próbuję odnaleźć liczbę W oznaczająca maksymalną sumę współczynników atrakcyjności (pierwszy wiersz wyjścia). Za wypisanie jej prawidłowo dostaje się 40% pkt. za test. Niestety od dłuższego czasu zatrzymałem się w momencie, w którym dostaje 40% za wszystkie testy oprócz jednego - 4d, w którym zamiast 473348 mój program wypisuje 473347. Zrobiłem "rekonesans" (wysyłając mnóstwo zgłoszeń i zamiast odpowiedzi wypisując wejście) i wiem, że w tym teście wszystkie współczynniki wynoszą 1, a n = 999999. Niestety nic mi to nie dało i wciąż nie mogę odnaleźć błędu.
Oto co robi mój program:
- Po wczytaniu danych szukam wierzchołka odpowiedniego na korzeń (czyli jakiegokolwiek, który nie jest liściem) i buduję drzewo (funkcja
budujDrzewo
). - Wywołuję funkcję rekurencyjną
oblicz
, która oblicza wartości dla danego wierzchołka na podstawie wyników jego dzieci:
- wynikO - wynik dla danego wierzchołka, jeśli jest wierzchołkiem odpoczynkowym: suma jego wszystkich dzieci + najbardziej korzystna droga w dół
- wynikZ - wynik dla wierzchołka, jeśli jest zwiedzany: punkty za wierzchołek + najbardziej korzystna droga w dół
- Wyniki ścieżek dla wierzchołka jeśli byłby najwyższym wierzchołkiem w ścieżce (startowym).
Tutaj kod:
#include <bits/stdc++.h>
using namespace std;
struct Wezel
{
int numer;
Wezel* ojciec;
vector<Wezel*> dzieci;
long long punkty;
long long wynikO,wynikZ;
int glebokosc;
bool obliczone;
};
const int MAX_N=1000000;
int punkty[MAX_N];
vector<int> polaczenia[MAX_N];
int glebokosci[MAX_N];
long long wynikMaksymalny=0;
Wezel* wezelStartowy;
void budujDrzewo(Wezel* korzen)
{
stack<pair<Wezel*,int>> s;
s.push(make_pair(korzen,0));
while(!s.empty())
{
pair<Wezel*,int> p = s.top();
s.pop();
for(int i = 0; i < polaczenia[p.second].size(); ++i)
{
if(glebokosci[polaczenia[p.second][i]]!=-1)
{
continue;
}
Wezel* dziecko = new Wezel();
dziecko->numer=polaczenia[p.second][i];
dziecko->ojciec=p.first;
dziecko->punkty=punkty[polaczenia[p.second][i]];
dziecko->glebokosc=p.first->glebokosc+1;
glebokosci[dziecko->numer]=dziecko->glebokosc;
p.first->dzieci.push_back(dziecko);
dziecko->wynikZ=0;
dziecko->wynikO=0;
dziecko->obliczone=0;
s.push(make_pair(dziecko,polaczenia[p.second][i]));
}
}
}
void oblicz(Wezel* w)
{
w->obliczone=1;
long long sumaDzieci=0;
pair<long long, long long> najwiekszeZ[2] { make_pair(0,0), make_pair(0,0)};
long long najwiekszeO[2] {0,0};
for(int i = 0; i < w->dzieci.size(); ++i)
{
if(!w->dzieci[i]->obliczone)
oblicz(w->dzieci[i]);
sumaDzieci += w->dzieci[i]->punkty;
if(w->dzieci[i]->wynikZ > najwiekszeZ[0].first || (w->dzieci[i]->wynikZ == najwiekszeZ[0].first && w->dzieci[i]->punkty <= najwiekszeZ[0].second))
{
najwiekszeZ[1] = najwiekszeZ[0];
najwiekszeZ[0].first = w->dzieci[i]->wynikZ;
najwiekszeZ[0].second = w->dzieci[i]->punkty;
}
else if(w->dzieci[i]->wynikZ > najwiekszeZ[1].first || (w->dzieci[i]->wynikZ == najwiekszeZ[1].first && w->dzieci[i]->punkty <= najwiekszeZ[1].second))
{
najwiekszeZ[1].first = w->dzieci[i]->wynikZ;
najwiekszeZ[1].second = w->dzieci[i]->punkty;
}
if(w->dzieci[i]->wynikO > najwiekszeO[0])
{
najwiekszeO[1] = najwiekszeO[0];
najwiekszeO[0] = w->dzieci[i]->wynikO;
}
else if(w->dzieci[i]->wynikO > najwiekszeO[1])
{
najwiekszeO[1] = w->dzieci[i]->wynikO;
}
}
sumaDzieci -= najwiekszeZ[0].second;
w->wynikO = sumaDzieci + najwiekszeZ[0].first;
w->wynikZ = w->punkty + najwiekszeO[0];
long long wynikSciezkiZ = w->wynikZ + najwiekszeO[1];
long long wynikSciezkiO = w->wynikO + najwiekszeZ[1].first - najwiekszeZ[1].second;
long long wynikWezla = max(wynikSciezkiZ, wynikSciezkiO);
//cout << "Wynik wezla " << w->numer+1 << ": " << wynikWezla << endl;
if(wynikWezla > wynikMaksymalny)
{
wynikMaksymalny = wynikWezla;
wezelStartowy = w;
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
int n;
cin>>n;
for(int i = 0; i < n; ++i)
{
cin>>punkty[i];
glebokosci[i]=-1;
}
for(int i = 0; i < n-1; ++i)
{
int a,b;
cin>>a>>b;
--a;
--b;
polaczenia[a].push_back(b);
polaczenia[b].push_back(a);
}
int k=0;
for(int i = 0; i < MAX_N; ++i)
{
if(polaczenia[i].size()>0)
{
k=i;
break;
}
}
Wezel* korzen = new Wezel();
korzen->punkty=punkty[k];
korzen->numer=k;
korzen->glebokosc=0;
glebokosci[korzen->numer]=0;
budujDrzewo(korzen);
oblicz(korzen);
cout << wynikMaksymalny << "\n1\n1";
}
Skończyły mi się już pomysły na to, co może iść nie tak. Napisałem nawet algorytm od nowa i niestety wynik jest ten sam. Proszę o pomoc.