Cod sursa(job #1753011)

Utilizator dtoniucDaniel Toniuc dtoniuc Data 5 septembrie 2016 17:57:21
Problema Cuplaj maxim in graf bipartit Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.41 kb
#include <fstream>
#include <vector>
#include <queue>

using namespace std;

typedef struct vertex
{
	int id;
	bool validFlag;
	bool marked;
	bool dfsMarked;
	bool isLeft;

	struct vertex* leftMatched;
	struct vertex* rightMatched;
	vector<vertex*> adjencyList;
} Vertex;

Vertex** CreateVector(int n, bool isLeft);
bool DoDfs(int k, Vertex* startNode, Vertex** leftList, Vertex** rightList);
void ReadEdges(int e, Vertex** leftList, Vertex** rightList, istream &fin);

int main()
{
    ifstream fin;
    ofstream fout;
    fout.open("cuplaj.out");
    fin.open("cuplaj.in");

    int n, m, e;
    fin >> n >> m >> e;

    Vertex** leftVertexList = CreateVector(n, true);
    Vertex** rightVertexList = CreateVector(m, false);

    ReadEdges(e, leftVertexList, rightVertexList, fin);

    bool modify = true;
    int k = 1;

	while(modify)
	{

		modify = false;

		for(int i = 1; i <= n; i++)
		{
			if(leftVertexList[i]->marked == false)
			{
				if(DoDfs(k, leftVertexList[i], leftVertexList, rightVertexList))
				{
					modify = true;
				}

				for(int i = 1; i <= n; i++)
					leftVertexList[i]->dfsMarked = false;

				for(int i = 1; i <= m; i++)
					rightVertexList[i]->dfsMarked = false;
			}
		}

		for(int i = 1; i <= n; i++)
			leftVertexList[i]->validFlag = true;

		for(int i = 1; i <= m; i++)
			rightVertexList[i]->validFlag = true;

		k+=2;
	}

	int matchNumber = 0;
	for(int i = 1; i <= m; i++)
	{
		if(rightVertexList[i]->leftMatched)
			matchNumber++;
	}

	fout << matchNumber << "\n";
	for(int i = 1; i <= m; i++)
	{
		if(rightVertexList[i]->leftMatched)
			fout << rightVertexList[i]->leftMatched->id << " " << rightVertexList[i]->id << "\n";

	}

    fin.close();
    fout.close();
    return 0;
}

bool DoDfs(int k, Vertex* startNode, Vertex** leftList, Vertex** rightList)
{
	if (k < 0)
		return false;

	if(k == 0 && startNode->marked == false)
	{
		startNode->marked = true;
		startNode->validFlag = false;

		return true;
	}

	startNode->dfsMarked = true;

	for(int i = 0; i < startNode->adjencyList.size(); i++)
	{
		Vertex* y = startNode->adjencyList[i];

		if(y->validFlag == true && y->dfsMarked == false)
		{
			if(startNode->isLeft)
			{
				if(DoDfs(k-1, y, leftList, rightList))
				{
					if(startNode->rightMatched != NULL && startNode == startNode->rightMatched->leftMatched && startNode->rightMatched != y)
					{
						startNode->rightMatched->leftMatched = NULL;
					}
					startNode->rightMatched = y;

					if(y->leftMatched != NULL && y->leftMatched != startNode )
					{
						y->leftMatched->rightMatched = NULL;
					}
					y->leftMatched = startNode;

					startNode->validFlag = false;
					startNode->marked = true;

					return true;
				}
			}
			if(!startNode->isLeft && y->marked)
			{
				if(DoDfs(k-1, y, leftList, rightList))
				{
					startNode->validFlag = false;
					startNode->marked = true;

					return true;
				}
			}
		}
	}

	return false;
}

Vertex** CreateVector(int n, bool isLeft)
{
	Vertex **list = new Vertex*[n + 1]();

    for(int i = 1; i <= n; i++)
    {
    	list[i] = new Vertex();
    	list[i]->id = i;
    	list[i]->validFlag = true;
    	list[i]->leftMatched = NULL;
    	list[i]->rightMatched = NULL;
    	list[i]->isLeft = isLeft;
    }

    return list;
}


void ReadEdges(int e, Vertex** leftList, Vertex** rightList, istream &fin)
{
	int x, y;

	for(int i = 1; i <= e; i++)
	{
		fin >> x >> y;
		leftList[x]->adjencyList.push_back(rightList[y]);
		rightList[y]->adjencyList.push_back(leftList[x]);
	}
}