Cod sursa(job #363341)

Utilizator andrei.sfrentSfrent Andrei andrei.sfrent Data 12 noiembrie 2009 20:16:56
Problema Critice Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.89 kb
#include <cstdio>
#include <queue>
#include <vector>
#include <string.h>

using namespace std;

#define MAXN 1001
#define MAXM 10001

#define INFINIT 1 << 30

struct muchie { int x, y; };
muchie vm[ MAXM ]; //vector de muchii citite din fisier
int crit[ MAXM ]; //vector muchii critice

vector<int> g[MAXN]; //liste de adiacenta
queue<int> q; //coada pentru breadth-first

int f[ MAXN ][ MAXN ]; //flux 
int c[ MAXN ][ MAXN ]; //capacitati
int n, m; //nr noduri, nr muchii
int pred[ MAXN ];
int w1[MAXN], w2[MAXN]; //vectori "vizitat" pentru gasirea muchiilor critice
int nMC;

inline int min(int a, int b)
{
	if(a < b) return a;
	return b;
}

inline int abs(int a)
{
	if(a >= 0) return a;
	return -a;
}

void citeste()
{
	int i, x, y, capacitate;
	scanf("%d%d", &n, &m);
	for(i = 1; i <= m; ++i)
	{
		scanf("%d%d%d", &x, &y, &capacitate);
		vm[ i ].x = x;
		vm[ i ].y = y;
		c[x][y] = c[y][x] = capacitate;
		g[x].push_back(y);
		g[y].push_back(x);
	}
}

int bfs_ford()
{
	int e, v;
	vector<int> :: iterator i; //iterator pentru vecinii unui nod
	memset(pred, 0, sizeof(pred)); //golesc vectorul pred
	q.push(1); //pun in coada sursa retelei de transport
	while(q.size() > 0) //cat timp inca am elemente in coada
	{
		e = q.front(); 
		q.pop(); //scot primul element din coada

		for(i = g[e].begin(); i != g[e].end(); ++i) //pentru fiecare vecin pe care il are nodul e
		{
			v = *i;
			if(c[e][v] == f[e][v] || v == 1 || pred[v] != 0) continue; 
			//nu ma intereseaza muchiile pline, nodul de plecare sau nodurile deja vizitate
			pred[v] = e;
			q.push(v);
		}
	}
	return (pred[n] != 0);
}

void ford_fulkerson() //umplu reteaua de transport cu pisici
{
	int inc, v, u;
	vector<int> :: iterator i;
	while(bfs_ford()) //cat timp gasesc un drum de ameliorare
	{
		inc = INFINIT;
		for(i = g[n].begin(); i != g[n].end(); ++i)
		{
			v = *i;
			if(c[v][n] == f[v][n]) continue;
			pred[n] = v;
			for(u = n; pred[u]; u = pred[u]) inc = min(inc, c[pred[u]][u] - f[pred[u]][u]);
			for(u = n; pred[u]; u = pred[u])
			{
				v = pred[u];
				f[v][u] += inc;
				f[u][v] -= inc;
			}
		}
	}
}

void bfs_critice(int nodPlecare, int* viz)
{
	int e, v;
	vector<int> :: iterator i;
	q.push(nodPlecare);
	viz[nodPlecare] = 1;
	while(q.size() > 0)
	{
		e = q.front();
		q.pop();

		for(i = g[e].begin(); i != g[e].end(); ++i)
		{
			v = *i;
			if(viz[v] || abs(c[e][v]) - abs(f[e][v]) == 0) continue;
			viz[v] = 1;
			q.push(v);
		}
	}
}

void gaseste_muchii_critice()
{
	int i, x, y;
	for(i = 1; i <= m; ++i)
	{
		x = vm[i].x;
		y = vm[i].y;
		if( ( w1[ x ] && w2[ y ] ) || ( w2[ x ] && w1[ y ] ) ) crit[++nMC] = i;
	}
}

void rezolva()
{
	ford_fulkerson();
	bfs_critice(1, w1);
	bfs_critice(n, w2);
	gaseste_muchii_critice();
}

void scrie()
{
	int i;
	printf("%d\n", nMC);
	for(i = 1; i <= nMC; ++i)
		printf("%d\n", crit[i]);
}

int main()
{
	freopen("critice.in", "r", stdin);
	freopen("critice.out", "w", stdout);
	citeste();
	rezolva();
	scrie();
	return 0;
}