P4929 【模板】舞蹈链(DLX)

1 篇文章 0 订阅

洛谷 4929

代码参考 https://www.acwing.com/solution/content/26693/

#include <iostream>
#include <vector>
#include <cstdio>

using namespace std;

const int N = 510;
int n, m, x;
vector<int> res;

struct DLX {
	DLX *left, *right, *up, *down;
	int row, col;
	int count;
	int ele;
	
	DLX() {
		left = right = up = down = nullptr;
		row = col = ele = -1;
		count = 0;
	}
	
}table[N][N];

void init() {
	for(int i = 0; i < n; i++) {
		table[i][0].down = &table[i + 1][0];
		table[i + 1][0].up = &table[i][0];
		table[i][0].row = i, table[i][0].col = 0;
		table[i + 1][0].row = i + 1, table[i + 1][0].col = 0;
	}
	for(int i = 0; i < m; i++) {
		table[0][i].right = &table[0][i + 1];
		table[0][i + 1].left = &table[0][i];
		table[0][i].row = 0, table[0][i].col = i;
		table[0][i + 1].row = 0, table[0][i + 1].col = i + 1;
	}
}

void insertCol(int row, int col) {
	DLX *p = &table[0][col];
	while(p) {
		DLX *next = p -> down;
		if(next == nullptr) break;
		else if(next -> row > row) break;
		else if(next -> row == row) {
			return ;
		}
		p = next;
	}
	DLX *cur = &table[row][col];
	if(p -> down) p -> down -> up = cur;
	cur -> down = p -> down;
	
	p -> down = cur;
	cur -> up = p; 
	table[0][col].count++;
}

void insertRow(int row, int col) {
	DLX *p = &table[row][0];
	while(p) {
		DLX *next = p -> right;
		if(next == nullptr) break;
		else if(next -> col > col) break;
		else if(next -> col == col) return ;
		p = next;
	}
	DLX *cur = &table[row][col];
	if(p -> right) p -> right -> left = cur; 
	cur -> right = p -> right;
	
	p -> right = cur;
	cur -> left = p;  
}

void add(int ele, int x, int y) {
	table[x][y].ele = ele;
	table[x][y].row = x;
	table[x][y].col = y;
	
	insertCol(x, y);
	insertRow(x, y);
}

void remove(DLX *col) {
	if(col -> right) col -> right -> left = col -> left;
	col -> left -> right = col -> right;
	
	DLX *cur = col -> down;
	while(cur) {
		int r = cur -> row;
		DLX *row = &table[r][0];
		while(row) {
			if(row -> col != 0) {
				table[0][row -> col].count--;
			}
			if(row -> col == col -> col) {
				row = row -> right;
				continue;
			}
			if(row -> down) row -> down -> up = row -> up;
			row -> up -> down = row -> down;
			row = row -> right;
		}
		cur = cur -> down;
	}
	  
}

void resume(DLX *col) {
	DLX *cur = col -> down;
	while(cur) {
		int r = cur -> row;
		DLX *row = &table[r][0];
		
		while(row) {
			if(row -> col != 0) {
				table[0][row -> col].count++;
			}
			if(row -> down) row -> down -> up = row;
			row -> up -> down = row;
			row = row -> right;
		}
		
		cur = cur -> down;
	}
	if(col -> right) col -> right -> left = col;
	col -> left -> right = col;
}


bool dfs() {
	int maxn = N * N;  // 我这里只设置为N + 1会有三个点re,不明白为什么,一列的最大值不是不超过N吗
	DLX *p = table[0][0].right, *q = nullptr;
	if(p == nullptr) return true;
	
	while(p) {
		if(p -> count != -1 && p -> count < maxn) {
			maxn = p -> count;
			q = p;
		}
		p = p -> right;
	}
	
	remove(q);
	
	{
		p = q -> down;
		while(p) {
			res.push_back(p -> row);
			DLX *temp = table[p -> row][0].right;
			while(temp) {
				if(temp -> col != q -> col) {
					remove(&table[0][temp -> col]);
				}
				temp = temp -> right;
			}
			
			if(dfs()) return true;
			
			res.pop_back();
			temp = table[p -> row][0].right;
			while(temp) {
				if(temp -> col != q -> col) {
					resume(&table[0][temp -> col]);
				}
				temp = temp -> right;
			}
			p = p -> down;
		}
	}
	resume(q);
	return false;
}

int main() {
	// freopen("in.txt", "r", stdin);
	cin >> n >> m;
	init();
	
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			cin >> x;
			if(x) add(x, i, j);
		}
	}
	
	if(dfs()) {
		for(int i : res) cout << i << ' ';
		puts("");
	} else puts("No Solution");
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值