Rezolvare completă PbInfo #2169 cezar1

În Roma antică există n așezări senatoriale distincte, câte una pentru fiecare dintre cei n senatori ai Republicii. Așezările senatoriale sunt numerotate de la 1 la n, între oricare două așezări existând legături directe sau indirecte. O legătură este directă dacă ea nu mai trece prin alte așezări senatoriale intermediare. Edilii au pavat unele dintre legăturile directe dintre două așezări (numind o astfel de legătură pavată stradă), astfel încât între oricare două așezări senatoriale să existe o singură succesiune de străzi prin care se poate ajunge de la o așezare senatorială la cealaltă.

Toţi senatorii trebuie să participe la şedinţele Senatului. In acest scop, ei se deplasează cu lectica. Orice senator care se deplasează pe o stradă plăteşte 1 ban pentru că a fost transportat cu lectica pe acea stradă.
La alegerea sa ca prim consul, Cezar a promis că va dota Roma cu o lectică gratuită care să circule pe un număr de k străzi ale Romei astfel încât orice senator care va circula pe străzile respective, să poată folosi lectica gratuită fără a plăti. Străzile pe care se deplasează lectica gratuită trebuie să fie legate între ele (zborul, metroul sau teleportarea nefiind posibile la acea vreme).

În plus, Cezar a promis să stabilească sediul sălii de şedinţe a Senatului într-una dintre aşezările senatoriale aflate pe traseul lecticii gratuite. Problema este de a alege cele k străzi şi amplasarea sediului sălii de şedinţe a Senatului astfel încât, prin folosirea transportului gratuit, senatorii, în drumul lor spre sala de şedinţe, să facă economii cât mai însemnate. În calculul costului total de transport, pentru toţi senatorii, Cezar a considerat că fiecare senator va călători exact o dată de la aşezarea sa până la sala de şedinţe a Senatului.

Cerința

Scrieţi un program care determină costul minim care se poate obţine prin alegerea adecvată a celor k străzi pe care va circula lectica gratuită şi a locului de amplasare a sălii de ședință a Senatului.

Date de intrare

Fișierul de intrare cezar1.in conţine pe prima linie două valori n k separate printr-un saţiu reprezentând numărul total de senatori şi numărul de strazi pe care circulă lectica gratuită. Pe următorele n-1 linii se află câte două valori i j separate printr-un spaţiu, reprezentând numerele de ordine a două aşezări senatoriale între care există stradă.

Date de ieșire

Fișierul de ieșire cezar1.out Pe prima linie a fişierului cezar.out se va scrie costul total minim al transportării tuturor senatorilor pentru o alegere optimă a celor k străzi pe care va circula lectica gratuită şi a locului unde va fi amplasată sala de şedinţe a Senatului.

Restricții și precizări

  • 1 < n ≤ 10000, 0 < k < n
  • 1 ≤ i, j ≤ n , i≠j
  • Oricare două perechi de valori de pe liniile 2, 3, …, n din fișierul de intrare reprezintă două străzi distincte.
  • Perechile din fişierul de intrare sunt date astfel încât respectă condiţiile din problemă.
  • Pentru 25% din teste n ≤ 30, pentru 25% din teste 30 < n ≤ 1000, pentru 25% din teste 1000 < n ≤ 3000, pentru 10% din teste 3000 < n ≤ 5000, pentru 10% din teste 5000 < n ≤ 10000.

Exemplu

cezar1.in

13 3
1 2
2 3
2 8
7 8
7 5
5 4
5 6
8 9
8 10
10 11
10 12
10 13

cezar1.out

11

Explicație

Costul minim se obţine, de exemplu, pentru alegerea celor 3 străzi între aşezările 5-7, 7-8, 8-10 și a sălii de şedințe a Senatului în aşezarea 8 (după cum este evidenţiat în desen). Există şi alte alegeri pentru care se obţine soluţia 11.

Cum e corect?

cout < "As la info"; cout << "As la info"; cout >> "As la info";

Felicitări! Poți mai mult?

Avem sute de probleme pentru tine, fiecare cu explicații ușor de înțeles.

Greșit, dar nu-i bai!

Antrenează-te cu sutele de probleme pe care ți le-am pregătit. Îți explicăm fiecare problemă în parte.

Rezolvare

Iată rezolvarea de 100 de puncte pentru problema cezar1:

#include <fstream>

using namespace std;

struct NOD
{
    int nod;
    NOD* next;
};
NOD *dp[10000];
int s, *c, n, k, h[10001], lh;

void Add(NOD*& p, int a)
{
    NOD* q;
    q = new(NOD);
    q->next = p;
    q->nod = a;
    p = q;
}

void Remove(NOD*& p, int a)
{
    NOD *q, *r;
    if (p->nod == a)
    {
        q = p;
        p = p->next;
        delete q;
    }
    else
    {
        q = p;
        while (q->next->nod != a)
            q = q->next;
        r = q->next;
        q->next = q->next->next;
        delete r;
    }
}

void Citire()
{
    int i, x, y;
    ifstream f("cezar1.in");
    f >> n >> k;
    c=new int[10000];
    for (i = 0; i < n; i++)
    {
        *(c + i) = 1;
        dp[i] = 0;
        h[i] = n;
    }
    for (i=0;i<n-1;i++)
    {
        f >> x >> y;
        Add(dp[x - 1], y - 1);
        Add(dp[y - 1], x - 1);
    }
    for (i = 0; i < n; i++)
        if (!dp[i]->next) h[++lh] = i;
     *(c+n) = 20000;
     h[n] = n;
     f.close();
}

void Desfrunzire()
{
    int ii, i, j, pmin;
    s = 0;
    for (ii = n - 1; ii >= k + 1; ii--)
    {
        pmin = h[1];
        s += *(c + pmin);
        j = dp[pmin]->nod;
        *(c + j) += *(c + pmin);
        Remove(dp[j], pmin);
        if(!dp[j]->next) h[1] = j;
        else
        {
            h[1] = h[lh];
            h[lh] = n;
            lh--;
        }
        i = 1;
        while (2 * i <= lh)
        {
            if (*(c + h[2 * i]) < *(c + h[2 * i + 1])) j = 2 * i;
            else j = 2 * i + 1;
            if (*(c + h[i]) > *(c + h[j]))
            {
                int aux = h[i];
                h[i] = h[j];
                h[j] = aux;
                i = j;
            }
            else i = n;
        }
    }
}

int main()
{
    Citire();
    Desfrunzire();
    ofstream f("cezar1.out");
    f << s << "\n";
    f.close();
    return 0;
}

Atenție

Enunțurile afișate pe această pagină aparțin exclusiv site-ului PbInfo. Astfel, pentru ștergerea conținutului, puteți să ne contactați la adresa Adresa de email.

Rezolvarea problemei #2169 cezar1

Pe această pagină găsești rezolvarea de 100 de puncte pentru problema #2169 cezar1 de pe PbInfo.ro. Atenție: nu încurajăm copiatul codului! Totuși, credem cu tărie că analizarea unei soluții corecte este o metodă foarte ușoară de a învăța informatică, astfel că oferim sursele pentru peste 1500 de probleme de pe platforma PbInfo.ro.

Pentru rezolvări PbInfo de la peste 1500 de probleme, vă invităm să intrați pe site-ul nostru!