Cod sursa(job #794589)

Utilizator tzipleatudTudor Tiplea tzipleatud Data 6 octombrie 2012 16:55:27
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.03 kb
#include <fstream>
#include <vector>
#include <queue>
#include <cstring>
#define NM 610
#define INF 0x3f3f3f3f

using namespace std;

ifstream f("cmcm.in");
ofstream g("cmcm.out");

int N,M,E;
int S,D;
int a,b,c,d;
int i,j;
int F[NM][NM],C[NM][NM];
int Cost[NM][NM];
int Dist[NM];
int T[NM];
queue<int> Q;
int ANS,CANS,FMIN;
vector<int> G[NM];
vector<int>::iterator it;
vector< pair<int, int> > Edges;
bool InQ[NM];

bool BF ()
{
    memset(Dist,INF,sizeof(Dist));
    Dist[S]=0;
    Q.push(S);
    InQ[S]=1;

    while (!Q.empty())
    {
        a=Q.front();
        Q.pop();
        InQ[a]=0;

        for (it=G[a].begin(); it!=G[a].end(); ++it)
        {
            if (C[a][*it]-F[a][*it]<=0 || Dist[a]+Cost[a][*it]>=Dist[*it]) continue;

            Dist[*it]=Dist[a]+Cost[a][*it];
            T[*it]=a;
            if (InQ[*it]) continue;
            InQ[*it]=1;
            Q.push(*it);
        }
    }

    return Dist[D]<INF;
}

int main ()
{
    f >> N >> M >> E;
    S=0;
    D=N+M+1;

    for (i=1; i<=N; i++)
    {
        C[S][i]=1;
        G[S].push_back(i);
        G[i].push_back(S);
    }

    for (i=1; i<=M; i++)
    {
        C[i+N][D]=1;
        G[D].push_back(i+N);
        G[i+N].push_back(D);
    }

    for (i=1; i<=E; i++)
    {
        f >> a >> b >> c;
        b+=N;
        C[a][b]=1;
        Cost[a][b]=c;
        Cost[b][a]=-c;
        G[a].push_back(b);
        G[b].push_back(a);
        Edges.push_back(make_pair(a,b));
    }

    while (BF())
    {
        FMIN=INF;
        for (i=D; i!=S; i=T[i])
            FMIN=min(FMIN,C[T[i]][i]-F[T[i]][i]);

        for (i=D; i!=S; i=T[i])
        {
            F[T[i]][i]+=FMIN;
            F[i][T[i]]-=FMIN;
        }

        ANS+=FMIN;
        CANS+=FMIN*Dist[D];
    }

    g << ANS << ' ' << CANS << '\n';

    for (i=0; i<Edges.size(); i++)
        if (F[Edges[i].first][Edges[i].second]>0)
            g << i+1 << ' ';

    g << '\n';
    f.close();
    g.close();
    return 0;
}