<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.algopedia.ro/wiki/index.php?action=history&amp;feed=atom&amp;title=Tmp_isa</id>
	<title>Tmp isa - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://www.algopedia.ro/wiki/index.php?action=history&amp;feed=atom&amp;title=Tmp_isa"/>
	<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Tmp_isa&amp;action=history"/>
	<updated>2026-04-13T09:22:19Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Tmp_isa&amp;diff=15846&amp;oldid=prev</id>
		<title>Bella at 20:14, 26 November 2018</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Tmp_isa&amp;diff=15846&amp;oldid=prev"/>
		<updated>2018-11-26T20:14:13Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
// Solutie Flux&lt;br /&gt;
// Tinca Matei&lt;br /&gt;
#include &amp;lt;bits/stdc++.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 8;&lt;br /&gt;
int x[2*MAX_N], y[2*MAX_N];&lt;br /&gt;
int num[2*MAX_N];&lt;br /&gt;
&lt;br /&gt;
// Clasa de flux maxim de cost minim&lt;br /&gt;
class MinCostMaxFlow {&lt;br /&gt;
    int n, src, dest;&lt;br /&gt;
&lt;br /&gt;
    // Lista de adiacenta&lt;br /&gt;
    vector&amp;lt;int&amp;gt; graph[1+2*MAX_N+1];&lt;br /&gt;
&lt;br /&gt;
    // Capacitatile pe fiecare muchie&lt;br /&gt;
    int kappa[1+2*MAX_N+1][1+2*MAX_N+1];&lt;br /&gt;
&lt;br /&gt;
    // Fluxul transmis pe fiecare muchie&lt;br /&gt;
    int flow[1+2*MAX_N+1][1+2*MAX_N+1];&lt;br /&gt;
&lt;br /&gt;
    // Parintele unui nod in arborele de la Bellman-Ford&lt;br /&gt;
    int papa[1+2*MAX_N+1];&lt;br /&gt;
&lt;br /&gt;
    // costul unei muchii din graf&lt;br /&gt;
    double cost[1+2*MAX_N+1][1+2*MAX_N+1];&lt;br /&gt;
&lt;br /&gt;
    // Cel mai bun cost de la sursa pana la nodul curent&lt;br /&gt;
    double bestcost[1+2*MAX_N+1];&lt;br /&gt;
&lt;br /&gt;
    // Pompeaza flux de la sursa la destinatie pe drumul in arborele de la Bellman-Ford&lt;br /&gt;
    void pump(int nod) {&lt;br /&gt;
        int i = nod;&lt;br /&gt;
        int fl = 10;&lt;br /&gt;
        // Initial trebuie sa calculam cat flux pompam pe drumul respectiv&lt;br /&gt;
        while(i != src) {&lt;br /&gt;
            fl = min(fl, kappa[papa[i]][i] - flow[papa[i]][i]);&lt;br /&gt;
            i = papa[i];&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Pompam fluxul propriu-zis pe drumul din arborele Bellman-Ford&lt;br /&gt;
        while(nod != 0) {&lt;br /&gt;
            flow[papa[nod]][nod] += fl;&lt;br /&gt;
            flow[nod][papa[nod]] -= fl;&lt;br /&gt;
            nod = papa[nod];&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Reactualizam cantitatea pompata de flux in total si costul in total&lt;br /&gt;
        maxfl += fl;&lt;br /&gt;
        mincost += bestcost[dest] * fl;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Baga Bellman-Ford; returneaza true daca a gasit un drum pe care poate pompa flux de la sursa la destinatie&lt;br /&gt;
    bool bellmanford() {&lt;br /&gt;
        deque&amp;lt;pair&amp;lt;int, double&amp;gt; &amp;gt; q;&lt;br /&gt;
&lt;br /&gt;
        // Initializam toate costurile cu infinit, in afara de costul sursei care va fi 0&lt;br /&gt;
        for(int i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
            bestcost[i] = 1000000000.0f;&lt;br /&gt;
        bestcost[src] = 0.0f;&lt;br /&gt;
&lt;br /&gt;
        // Bagam sursa in coada&lt;br /&gt;
        q.push_back(make_pair(src, 0.0f));&lt;br /&gt;
&lt;br /&gt;
        while(!q.empty()) {&lt;br /&gt;
            // Scoatem primul element din coada&lt;br /&gt;
            int nod = q.front().first;&lt;br /&gt;
            double costnod = q.front().second;&lt;br /&gt;
            q.pop_front();&lt;br /&gt;
&lt;br /&gt;
            // Reactualizam costurile minime pt fiecare vecin&lt;br /&gt;
            for(auto it: graph[nod]) {&lt;br /&gt;
                if(flow[nod][it] &amp;lt; kappa[nod][it] &amp;amp;&amp;amp; bestcost[nod] + cost[nod][it] &amp;lt; bestcost[it]) {&lt;br /&gt;
                    bestcost[it] = bestcost[nod] + cost[nod][it];&lt;br /&gt;
                    q.push_back(make_pair(it, bestcost[it]));&lt;br /&gt;
                    papa[it] = nod;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Exista drum de la sursa pana la destinatie&lt;br /&gt;
        if(bestcost[dest] &amp;lt; 1000000000.0f) {&lt;br /&gt;
            pump(dest);&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    int maxfl;&lt;br /&gt;
    double mincost;&lt;br /&gt;
&lt;br /&gt;
    // Initializeaza toate variabilele interne&lt;br /&gt;
    MinCostMaxFlow(int _n) {&lt;br /&gt;
        n = _n;&lt;br /&gt;
        src = 0;&lt;br /&gt;
        dest = n - 1;&lt;br /&gt;
        maxfl = mincost = 0;&lt;br /&gt;
        for(int i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
            for(int j = 0; j &amp;lt; n; ++j)&lt;br /&gt;
                kappa[i][j] = flow[i][j] = cost[i][j] = 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Adauga o muchie de la nodul a la nodul b cu capacitate k si cost c&lt;br /&gt;
    void pushEdge(int a, int b, int k, double c) {&lt;br /&gt;
        graph[a].push_back(b);&lt;br /&gt;
        graph[b].push_back(a);&lt;br /&gt;
        cost[a][b] = c;&lt;br /&gt;
        cost[b][a] = -c;&lt;br /&gt;
        kappa[a][b] = k;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Ruleaza algoritmul de flux&lt;br /&gt;
    void runFlow() {&lt;br /&gt;
        while(bellmanford());&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// Returneaza patratul lui x&lt;br /&gt;
double sqr(double x) {&lt;br /&gt;
    return x * x;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Returneaza distanta dintre doua puncte (x1, y1), (x2, y2)&lt;br /&gt;
double dist(double x1, double y1, double x2, double y2) {&lt;br /&gt;
    return sqrt(sqr(x1 - x2) + sqr(y1 - y2));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    int n;&lt;br /&gt;
    double rez = 1000000000.0f;&lt;br /&gt;
&lt;br /&gt;
    // Citirea numerelor&lt;br /&gt;
    FILE *fin = fopen(&amp;quot;xd.in&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
    fscanf(fin, &amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
    for(int i = 0; i &amp;lt; 2 * n; ++i)&lt;br /&gt;
        fscanf(fin, &amp;quot;%d%d&amp;quot;, &amp;amp;x[i], &amp;amp;y[i]);&lt;br /&gt;
    fclose(fin);&lt;br /&gt;
&lt;br /&gt;
    // Impart toate casele in doua submultimi. Intre doua case din submultimi diferite&lt;br /&gt;
    // adaug o muchie de capacitate 1 si cost egal cu distanta dintre cele doua puncte&lt;br /&gt;
    for(int i = 0; i &amp;lt; (1 &amp;lt;&amp;lt; (2 * n)); ++i) {&lt;br /&gt;
        int cnt = 0;&lt;br /&gt;
        // Renumerotam toate casele; Cele din multimea A vor fi numerotate de la 1 pana la n,&lt;br /&gt;
        // iar cele din multimea B vor fi numerotate de la n + 1 pana la 2 * n&lt;br /&gt;
        for(int j = 0; j &amp;lt; 2 * n; ++j)&lt;br /&gt;
            if((1 &amp;lt;&amp;lt; j) &amp;amp; i) {&lt;br /&gt;
                cnt++;&lt;br /&gt;
                num[j] = cnt;&lt;br /&gt;
            } else&lt;br /&gt;
                num[j] = n + (j + 1) - cnt;&lt;br /&gt;
&lt;br /&gt;
        if(cnt == n) {&lt;br /&gt;
            MinCostMaxFlow flx(2 * n + 2);&lt;br /&gt;
&lt;br /&gt;
            // Construirea propriu-zisa a grafului&lt;br /&gt;
            for(int a = 0; a &amp;lt; 2 * n; ++a) {&lt;br /&gt;
                for(int b = 0; b &amp;lt; 2 * n; ++b)&lt;br /&gt;
                    if(((1 &amp;lt;&amp;lt; a) &amp;amp; i) &amp;gt; 0 &amp;amp;&amp;amp; ((1 &amp;lt;&amp;lt; b) &amp;amp; i) == 0)&lt;br /&gt;
                        flx.pushEdge(num[a], num[b], 1, dist(x[a], y[a], x[b], y[b]));&lt;br /&gt;
&lt;br /&gt;
                // Adaug o muchie de la sursa la fiecare nod din multimea A&lt;br /&gt;
                if((1 &amp;lt;&amp;lt; a) &amp;amp; i)&lt;br /&gt;
                    flx.pushEdge(0, num[a], 1, 0);&lt;br /&gt;
                else // Adaug o muchie de la fiecare nod din multimea B la destinatie&lt;br /&gt;
                    flx.pushEdge(num[a], 2 * n + 1, 1, 0);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // Rulez fluxul pe graful construit&lt;br /&gt;
            flx.runFlow();&lt;br /&gt;
&lt;br /&gt;
            // In graful construit, cuplajul trebuie sa fie perfect!!!&lt;br /&gt;
            assert(flx.maxfl == n);&lt;br /&gt;
&lt;br /&gt;
            // reactualizam rezultatul&lt;br /&gt;
            rez = min(rez, flx.mincost);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Afisam rezultatele&lt;br /&gt;
    FILE *fout = fopen(&amp;quot;xd.out&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
    fprintf(fout, &amp;quot;%.10f&amp;quot;, rez);&lt;br /&gt;
    fclose(fout);&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
&lt;br /&gt;
Graful construit:&lt;br /&gt;
&lt;br /&gt;
Noi ne construim un graf bipartit format din doua multimi A si B. Noi vrem sa cuplam fiecare nod din multimea A cu un nod din multimea B&lt;br /&gt;
Costul unei muchii dintre A si B va fi distanta dintre cele doua puncte pe care le reprezinta.&lt;br /&gt;
&lt;br /&gt;
Algoritmul de cuplaj maxim de cost minim se implementeaza cu ajutorul algoritmului de flux maxim de cost minim&lt;br /&gt;
&lt;br /&gt;
Avem sursa(0) si destinatia(2*n+1) si nodurile interne (cele din multimea A(1...N) si cele din multimea B(N+1...2N))&lt;br /&gt;
Intre sursa si fiecare nod din multimea A avem o muchie de capacitate 1 si cost 0&lt;br /&gt;
Intre fiecare nod din multimea B si destinatie avem o muchie de capacitate 1 si cost 0&lt;br /&gt;
Intre fiecare nod din multimea A si multimea B avem o muchie de capacitate 1 si cost egal cu distanta dintre cele doua puncte&lt;br /&gt;
&lt;br /&gt;
Capacitatile de la ultimul tip de muchii nu este asa de relevant, acesta poate fi infinita, atata timp cat este mai mare decat 1.&lt;br /&gt;
Celalalte muchii trebuie sa aiba capacitate neaparat 1&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bella</name></author>
	</entry>
</feed>