Cod sursa(job #1564219)

Utilizator TimitocArdelean Andrei Timotei Timitoc Data 9 ianuarie 2016 12:50:46
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.06 kb
#include <iostream>
#include <cstdio>
#include <vector>
#include <bitset>
#include <queue>
#define MAXN 700
#define MAXE 103000
#define inf 0x7fffffff

using namespace std;

int n, m, e, s, d, sol;
vector<int> graf[MAXN];
int edge[MAXN][MAXN], cost[MAXN][MAXN], capac[MAXN][MAXN], flow[MAXN][MAXN];
int tat[MAXN];

void citire()
{
	int x, y, c;
	scanf("%d %d %d", &n, &m, &e);
	for (int i = 1; i <= e; i++) {
		scanf("%d %d %d", &x, &y, &c);
		y += n;
		graf[x].push_back(y);
		graf[y].push_back(x);
		capac[x][y] = 1;
		edge[x][y] = edge[y][x] = i;
		cost[x][y] = c;
		cost[y][x] = -c;
	}
}

void prepare()
{
	s = 0; d = n+m+1;
	for (int i = 1; i <= n; i++) {
		graf[s].push_back(i);
		capac[s][i] = 1;
		cost[s][i] = 0;
	}
	for (int i = n+1; i <= n+m; i++) {
		graf[i].push_back(d);
		capac[i][d] = 1;
		cost[i][d] = 0;
	}
}

bitset<MAXN> einq;
queue<int> q;
int best[MAXN];

int bellman()
{
	for (int i = s; i <= d; i++) best[i] = inf;
	for (q.push(s), best[s] = 0, einq = 0; !q.empty(); q.pop()) {
        int nod = q.front();
        einq[nod] = 0;
        for (int i = 0, t = graf[nod].size(); i < t; i++) {
            int y = graf[nod][i];
            if (capac[nod][y]-flow[nod][y] && best[y] > best[nod] + cost[nod][y]) {
                best[y] = best[nod] + cost[nod][y];
				tat[y] = nod;
                if (!einq[y]) {
					q.push(y);
					einq[y] = 1;
                }
            }
        }
	}
	return best[d] != inf;
}

void solve()
{
	while (bellman()) {
        int mini = 1;
		sol += best[d];
		if (!mini) { cerr << "ERROR"; continue; }
		for (int i = d; i != s; i = tat[i]) {
			flow[tat[i]][i] += mini;
			flow[i][tat[i]] -= mini;
		}
	}
}

void print()
{
	int nr = 0;
	for (int i = 1; i <= n+m; i++)
		for (int j = 1; j <= n+m; j++)
			nr += (flow[i][j] == 1);
	printf("%d %d\n", nr, sol);
    for (int i = 1; i <= n+m; i++)
		for (int j = 1; j <= n+m; j++)
			if (flow[i][j] == 1)
                printf("%d ", edge[i][j]);
}

int main()
{
    freopen("cmcm.in", "r", stdin);
    freopen("cmcm.out", "w", stdout);

    citire();
    prepare();
    solve();
    print();

    return 0;
}