Cod sursa(job #989594)

Utilizator Cosmin1490Balan Radu Cosmin Cosmin1490 Data 25 august 2013 22:57:56
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 7.06 kb
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <fstream>
using namespace std;
   
const string file = "cmcm";
   
const string infile = file + ".in";
const string outfile = file + ".out";
 
int N, M, E;
int S, D;
int MinCost;
 
struct Arc
{
    int dst;
    int cap;
    int flux;
    int cost;
    int p;
 
    Arc(int dst, int cap, int cost, int p)
    {
        this->flux = 0;
        this->dst = dst;
        this->cap = cap;
        this->cost = cost;
        this->p = p;
    }
 
};
 
const int INF = 0x3f3f3f3f;
 
vector<Arc> arcs;
vector<vector<int> > G;
 
vector<int> potential;
vector<int> realD;
vector<int> potD;
 
vector<int> dijArc;
vector<int> dijParent;
 
 
vector<int> heap;
vector<int> poz;
 
void initHeap()
{
    heap.reserve(N + M + 3);
    heap.push_back(0);
    poz.resize(N + M + 3);
}
 
inline int father(int i)
{
    return i / 2;
}
 
inline int lSon(int i)
{
    return i * 2;
}
 
inline int rSon(int i)
{
    return i * 2 + 1;
}
 
void swapHeap(int a, int b)
{
    int aux = heap[a];
    heap[a] = heap[b];
    heap[b] = aux;
    poz[heap[a]] = a;
    poz[heap[b]] = b;
}
 
 
void upHeap(int i)
{
    while( i > 1 && potD[heap[i]] < potD[heap[father(i)]])
    {
        swapHeap(i, father(i));
        i = father(i);
    }
}
 
void downHeap(int i)
{
    while(true)
    {
        int size = heap.size();
        int min = i;
 
        if(lSon(i) < size && potD[heap[lSon(i)]] < potD[heap[min]])
            min = lSon(i);
 
        if(rSon(i) < size && potD[heap[rSon(i)]] < potD[heap[min]])
            min = rSon(i);
        if(min == i) 
            break;
        swapHeap(i, min);
        i = min;
 
    }
}
 
int topHeap()
{
    return heap[1];
}
 
void insertHeap(int i)
{
    poz[i] = heap.size();
    heap.push_back(i);
    upHeap(heap.size() - 1);
}
 
void popHeap()
{
    swapHeap(1, heap.size() - 1);
    poz[heap[heap.size() - 1]] = 0;
    heap.pop_back();
    downHeap(1);
}
 
bool emptyHeap()
{
    return heap.size() <= 1;
}
 
void Bellman()
{
    potential.resize(N + M + 3, INF);
    queue<int> q;
    vector<bool> inQ(N + M + 3);
    q.push(S);
    potential[S] = 0;
 
    while(q.empty() == false)
    {
        int current = q.front();
        q.pop();
        inQ[current] = false;
        for(vector<int>::iterator itr = G[current].begin();
            itr != G[current].end();
            itr++)
        {
            if(arcs[*itr].cap - arcs[*itr].flux > 0)
            {
                if(potential[arcs[*itr].dst] > potential[current] + arcs[*itr].cost)
                {
                    potential[arcs[*itr].dst] = potential[current] + arcs[*itr].cost;
 
                    if(inQ[arcs[*itr].dst] == false)
                    {
                        q.push(arcs[*itr].dst);
                        inQ[arcs[*itr].dst] = true;
                    }
                }
            }
        }
    }
}
 
bool Dijkstra()
{
    potD.clear();
    potD.resize(N + M + 3, INF);
    potD[S] = 0;
    realD[S] = 0;
 
    insertHeap(S);
 
    while(emptyHeap() == false)
    {
        int current = topHeap();
        popHeap();
 
        for(vector<int>::iterator itr = G[current].begin();
            itr != G[current].end();
            itr++)
        {
            if(arcs[*itr].cap - arcs[*itr].flux > 0)
            {
                int newCost = arcs[*itr].cost + potential[current] - potential[arcs[*itr].dst];
 
                if(potD[arcs[*itr].dst] > potD[current] + newCost)
                {
                    potD[arcs[*itr].dst] = potD[current] + newCost;
                    realD[arcs[*itr].dst] = realD[current] + arcs[*itr].cost;
 
                    dijParent[arcs[*itr].dst] = current;
                    dijArc[arcs[*itr].dst] = *itr;
 
                    if(poz[arcs[*itr].dst] == 0)
                    {
                        insertHeap(arcs[*itr].dst);
                    }
                    else
                    {
                        upHeap(poz[arcs[*itr].dst]);
                    }
 
                }
            }
        }
    }
 
    potential = realD;
 
    if(potD[D] == INF) return false;
    return true;
}
 
 
int main()
{
    fstream fin(infile.c_str(), ios::in);
 
    fin >> N >> M >> E;
 
    G.resize(N + M + 1 + 2);
    arcs.reserve(2 * E + 2 * N + 2 * M);
    S = N + M + 1;
    D = N + M + 2;
 
    for(int i = 0; i < E; i++)
    {
        int x, y, c;
        fin >> x >> y >> c;
 
        y += N;
 
        G[x].push_back(arcs.size());
        G[y].push_back(arcs.size() + 1);
 
        Arc to(y, 1, c, arcs.size() + 1);
        Arc from(x, 0, -c, arcs.size());
 
        arcs.push_back(to);
        arcs.push_back(from);
 
    }
 
 
    for(int i = 1; i <= N; i++)
    {
        int x, y, c;
        x = S;
        y = i;
        c = 0;
 
        G[x].push_back(arcs.size());
        G[y].push_back(arcs.size() + 1);
 
        Arc to(y, 1, c, arcs.size() + 1);
        Arc from(x, 0, -c, arcs.size());
 
        arcs.push_back(to);
        arcs.push_back(from);
    }
 
 
    for(int i = N + 1; i <= N + M; i++)
    {
        int x, y, c;
        x = i;
        y = D;
        c = 0;
 
        G[x].push_back(arcs.size());
        G[y].push_back(arcs.size() + 1);
 
        Arc to(y, 1, c, arcs.size() + 1);
        Arc from(x, 0, -c, arcs.size());
 
        arcs.push_back(to);
        arcs.push_back(from);
    }
    fin.close();
 
    Bellman();
 
    realD.resize(N + M + 3);
    dijArc.resize(N + M + 3);
    dijParent.resize(N + M + 3);
 
    initHeap();
 
    while(Dijkstra())
    {
        int maxFlow = INF;
 
        for(int current = D; current != S; current = dijParent[current])
        {
            maxFlow = min(maxFlow, arcs[dijArc[current]].cap - arcs[dijArc[current]].flux);
        }
 
        for(int current = D; current != S; current = dijParent[current])
        {
            arcs[dijArc[current]].flux += maxFlow;
            arcs[arcs[dijArc[current]].p].flux -= maxFlow;
        }
 
        MinCost += maxFlow * realD[D];
 
    }
 
    int count = 0;
    for(int i = 0; i < 2 * E; i+=2)
    {
        if(arcs[i].flux != 0) 
            count++;
    }
 
    fstream fout(outfile.c_str(), ios::out);
    //cout << count << " " << MinCost << "\n";
    fout << count << " " << MinCost << "\n";
    for(int i = 0; i < 2 * E; i+=2)
    {
        if(arcs[i].flux != 0)
        {
            //cout << (i / 2) + 1 << " ";
            fout << (i / 2) + 1 << " ";
        }
    }
    fout << "\n";
    fout.close();
}