Cod sursa(job #661799)

Utilizator eukristianCristian L. eukristian Data 15 ianuarie 2012 11:50:20
Problema Critice Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.78 kb
#include <cstdio>
#include <cstring>
#include <algorithm>

#define INF 0x7FFFFFFF
#define MMax 10001
struct node {
	node *next;
	int key;
	int edgeIndex;
};

int n, m, capacity[1001][1001];
int flow[1001][1001], max_flow;
node *network[1001];

char color[1001];
int prev[1001], queue[1001];
int criticalEdges[10001], solCount;

bool bfs(int source, int sink);
void add(int n1, int n2, int cap, int edgeIndex);
void read();
void dinic();
void bfsAccess(int start, int id);
void bfsAccess2(int start, int id);

int main()
{
	read();
	dinic();

	memset(color, 0, sizeof(color));
	bfsAccess(1, 1);bfsAccess2(n, 2);

	for (int i = 1 ; i <= n ; ++i)
	{
		node *q = network[i];
		while (q)
		{
			if (flow[i][q->key] > 0 && (capacity[i][q->key] - flow[i][q->key] == 0) && (color[i] & 1) && (color[q->key] & 2))
				criticalEdges[++solCount] = q->edgeIndex;
			q = q->next;
		}
	}

	std::sort(criticalEdges + 1, criticalEdges + solCount + 1);
	printf("%d\n", solCount);
	for (int i = 1 ; i <= solCount ; ++i)
		printf("%d\n", criticalEdges[i]);
	return 0;
}

bool bfs(int source, int sink)
{
	int left = 0, right = 0;
	memset(color, 0, sizeof(color));
	queue[0] = source;
	color[0] = 1;

	while (left <= right)
	{
		int nd = queue[left++];
		if (nd == sink)
			continue;

		node *q = network[nd];

		while (q)
		{
			if (color[q->key] == 0 && (capacity[nd][q->key] - flow[nd][q->key]))
			{
				color[q->key] = 1;
				queue[++right] = q->key;
				prev[q->key] = nd;
			}

			q = q->next;
		}
	}

	return color[sink];
}

void add(int n1, int n2, int cap, int edgeIndex)
{
	node *q = new node;
	q->next = network[n1];
	q->key = n2;
	q->edgeIndex = edgeIndex;
	network[n1] = q;

	q = new node;
	q->next = network[n2];
	q->key = n1;
	q->edgeIndex = edgeIndex;
	network[n2] = q;

	capacity[n1][n2] = capacity[n2][n1] = cap;
}

void read()
{
	freopen("critice.in", "r", stdin);
	freopen("critice.out","w",stdout);

	scanf("%d%d", &n, &m);
	for (int i = 1 ; i <= m ; ++i)
	{
		int n1, n2, cap;
		scanf("%d%d%d", &n1, &n2, &cap);
		add(n1, n2, cap, i);
	}
}

void dinic()
{
	while (bfs(1, n))
	{
		node *q = network[n];
		while (q)
		{
			int bottleneck = INF;
			if (flow[q->key][n] == capacity[q->key][n] || color[q->key] == 0)
			{
				q = q->next;
				continue;
			}

			bottleneck = capacity[q->key][n] - flow[q->key][n];

			for (int crtNd = q->key ; crtNd != 1 ; crtNd = prev[crtNd])
			{
				if (capacity[prev[crtNd]][crtNd] - flow[prev[crtNd]][crtNd] < bottleneck)
					bottleneck = capacity[prev[crtNd]][crtNd] - flow[prev[crtNd]][crtNd];
			}

			if (bottleneck == 0)
			{
				q = q->next;continue;
			}

			flow[q->key][n] += bottleneck;
			flow[n][q->key] -= bottleneck;
			
			for (int crtNd = q->key ; crtNd != 1 ; crtNd = prev[crtNd])
			{
				flow[prev[crtNd]][crtNd] += bottleneck;
				flow[crtNd][prev[crtNd]] -= bottleneck;
			}

			max_flow += bottleneck;

			q = q->next;
		}
	}
}

void bfsAccess(int start, int id)
{
	int left = 0, right = 0;
	queue[left] = start;
	color[start] += id;

	while (left <= right)
	{
		int nd = queue[left++];

		node *q = network[nd];
		while (q)
		{
			if (color[q->key] != id && color[q->key] != 3 && (capacity[nd][q->key] - flow[nd][q->key] != 0))
			{
				color[q->key] += id;
				queue[++right] = q->key;
			}
			q = q->next;
		}
	}
}

void bfsAccess2(int start, int id)
{
	int left = 0, right = 0;
	queue[left] = start;
	color[start] += id;

	while (left <= right)
	{
		int nd = queue[left++];

		node *q = network[nd];
		while (q)
		{
			if (color[q->key] != id && color[q->key] != 3 && (capacity[nd][q->key] + flow[nd][q->key] != 0))
			{
				color[q->key] += id;
				queue[++right] = q->key;
			}
			q = q->next;
		}
	}
}