Cod sursa(job #84949)

Utilizator MariusMarius Stroe Marius Data 18 septembrie 2007 21:24:56
Problema Critice Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.39 kb
#include <cstdio>
#include <vector>
#include <memory.h>

using namespace std;

const char iname[] = "critice.in";
const char oname[] = "critice.out";

#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define edge(x, y) (C[x][y] - F[x][y] > 0)
#define modul(z) ((z) < 0 ? (-(z)) : (z))
#define MAXN  1007
#define MAXCAP  20000
#define PB push_back
#define MP make_pair

vector <int> G[MAXN];
vector < pair <int, int> > L;

int C[MAXN][MAXN], F[MAXN][MAXN];

int n, n_edges;


void read_in(void)
{
	int x, y, c;

	FILE *fi = fopen(iname, "r");

	fscanf(fi, "%d %d", &n, &n_edges);
	for (int i = 0; i < n_edges; ++ i) {
		fscanf(fi, "%d %d %d", &x, &y, &c);
		C[x][y] = C[y][x] = c;
		G[x].PB(y);
		G[y].PB(x);
		L.PB(MP(x, y));
	}
	fclose(fi);
}

int flow[MAXN], parent[MAXN], in_queue[MAXN], queue[MAXN], dist[MAXN];

int ways(int s, int t, int mark[], int dist[])
{
	int head, tail;

	memset(flow, 0, sizeof(flow));
	memset(parent, 0, sizeof(parent));

	for (flow[queue[head = tail = 0] = s] = MAXCAP; head <= tail; ++ head) {
		int x = queue[head];
		for (int i = (int)(G[x].size()); i --; ) {
			int y = G[x][i];
			if (mark[y] && edge(x, y) && (flow[y] == 0) && (dist[y] == dist[x] + 1)) {
				flow[queue[++ tail] = y] = MIN(flow[x], C[x][y] - F[x][y]);
				parent[y] = x;
			}
		}
	}
	for (int x = t; x != s && parent[x]; x = parent[x]) {
		int y = parent[x];
		F[y][x] += flow[t];
		F[x][y] -= flow[t];
		int meet_neigh = false;
		for (int i = (int)(G[y].size()); i --; ) {
			int z = G[y][i];
			if (mark[z] && edge(y, z) && dist[z] == dist[y] + 1)
				meet_neigh = true;
		}
		if (meet_neigh == false)
			mark[y] = false;
	}
	
	return flow[t];
}

int dinic(int s, int t)
{
	int flow = 0;
	int head, tail;
	
	memset(in_queue, 0, sizeof(in_queue));
	memset(dist, 0, sizeof(dist));

	for (in_queue[queue[head = tail = 0] = s] = true; head <= tail; ++ head) {
		int x = queue[head];
		for (int i = (int)(G[x].size()); i --; ) {
			int y = G[x][i];
			if (edge(x, y) && (in_queue[y] == false)) {
				in_queue[queue[++ tail] = y] = true;
				dist[y] = dist[x] + 1;
			}
		}
	}
	
	memset(in_queue, 0, sizeof(in_queue));

	for (in_queue[queue[head = tail = 0] = t] = true; head <= tail; ++ head) {
		int x = queue[head];
		for (int i = (int)(G[x].size()); i --; ) {
			int y = G[x][i];
			if (edge(y, x) && (in_queue[y] == false) && (dist[x] == dist[y] + 1))
				in_queue[queue[++ tail] = y] = true;
		}
	}

	while (true) {
		int f = ways(s, t, in_queue, dist);
		flow += f;
		if (f == 0 || in_queue[s] == false) 
			break ;
	}
	
	return flow;
}

void BF(int s, int value, int mark[]) 
{
	int head, tail;

	for (mark[queue[head = tail = 0] = s] = value; head <= tail; ++ head) {
		int x = queue[head];
		for (int i = (int)(G[x].size()); i --; ) {
			int y = G[x][i];
			if ((mark[y] == false) && (C[x][y] > modul(F[x][y])))
				mark[queue[++ tail] = y] = value;
		}
	}
}

int main(void)
{
	read_in();
	
	while (dinic(1, n) > 0) ;
	
	int mark[MAXN] = {0};
	BF(1, 1, mark);
	BF(n, 2, mark);

	int cnt_res = 0;
	for (int i = 0; i < n_edges; ++ i) {
		if (mark[L[i].first] + mark[L[i].second] == 3)
			cnt_res ++;
	}

	FILE *fo = fopen(oname, "w");
	
	fprintf(fo, "%d\n", cnt_res);
	for (int i = 0; i < n_edges; ++ i) {
		if (mark[L[i].first] + mark[L[i].second] == 3)
			fprintf(fo, "%d\n", i + 1);
	}
	fclose(fo);

	return 0;
}