URAL 1156 Two Rounds (DFS二分染色 + DFS枚举 + 剪枝)

#include <stdio.h>
#define MAX 110

int numOfTasks, numOfPairs;
int numOfProblems;
typedef struct Node{
	int to;
	int next;
}Node;
//用邻接链表存储题目
//注意数组别开小了,千万别只是开MAX的大小!!!
Node NodeArray[MAX * 2];
int numOfNodes;
int head[MAX];

int problemColor[MAX];

typedef struct Set{
	int colorStack[3][MAX];
	int colorTop[3];
	int colorInRound1;
}Set;
Set SetArray[MAX];
int numOfSets;

int fail;
int divided;

void addPair(int from, int to){
	numOfNodes++;
	NodeArray[numOfNodes].to = to;
	NodeArray[numOfNodes].next = head[from];
	head[from] = numOfNodes;
}

void colorPairedProblems(int problem, int SetNum, int color){	
	problemColor[problem] = color;
	int top = ++(SetArray[SetNum].colorTop[color]);
	SetArray[SetNum].colorStack[color][top] = problem;
	int pairColor = 3 - color;
	int i, pairedProblem, pairedProblemColor;
	for (i = head[problem]; i != 0; i = NodeArray[i].next){
		pairedProblem = NodeArray[i].to;
		pairedProblemColor = problemColor[pairedProblem];
		if (pairedProblemColor == color){
			fail = 1;
			return;
		}
		if (pairedProblemColor == 0)
			colorPairedProblems(pairedProblem, SetNum, pairColor);
		if (fail)
			return;
	}
}

void divideIntoRounds(int SetNum, int numOfTasksInRound1, int numOfTaskInBound2){
	if (SetNum == numOfSets + 1){
		if (numOfTasksInRound1 == numOfTasks)
			divided = 1;
		return;
	}
	//必须用通过计算两个round的task的数量来剪枝,可以大大地提高效率(不比用分组背包做差),不然会超时
	if (numOfTasksInRound1 > numOfTasks || numOfTaskInBound2 > numOfTasks)
		return;

	SetArray[SetNum].colorInRound1 = 1;
	divideIntoRounds(SetNum + 1, numOfTasksInRound1 + SetArray[SetNum].colorTop[1], numOfTaskInBound2 + SetArray[SetNum].colorTop[2]);
	if (divided)
		return;

	SetArray[SetNum].colorInRound1 = 2;
	divideIntoRounds(SetNum + 1, numOfTasksInRound1 + SetArray[SetNum].colorTop[2],numOfTaskInBound2 + SetArray[SetNum].colorTop[1]);
	if (divided)
		return;
}

int main(){
	
	scanf("%d%d", &numOfTasks, &numOfPairs);
	numOfProblems = numOfTasks << 1;
	int i, one, another;
	for (i = 1; i <= numOfPairs; i++){
		scanf("%d%d", &one, &another);
		addPair(one, another);
		addPair(another, one);
	}

	for (i = 1; i <= numOfProblems; i++){
		if (problemColor[i] == 0){
			numOfSets++;	
			colorPairedProblems(i, numOfSets, 1);
		}
		if (fail){
			printf("IMPOSSIBLE\n");
			return 0;
		}
	}

	divideIntoRounds(1, 0, 0);

	if (divided == 0){
		printf("IMPOSSIBLE\n");
		return 0;
	}

	Set tempSet;
	int  colorInRound1, top, j;
	for (i = 1; i <= numOfSets; i++){
		tempSet = SetArray[i];
		colorInRound1 = tempSet.colorInRound1;
		top = tempSet.colorTop[colorInRound1];
		for (j = 1; j <= top; j++)
			printf("%d ", tempSet.colorStack[colorInRound1][j]);
	}
	printf("\n");

	int colorInRound2;
	for (i = 1; i <= numOfSets; i++){
		tempSet = SetArray[i];
		colorInRound2 = 3 - tempSet.colorInRound1;
		top = tempSet.colorTop[colorInRound2];
		for (j = 1; j <= top; j++)
			printf("%d ", tempSet.colorStack[colorInRound2][j]);
	}
	printf("\n");

	return 0;
}


 

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值