东方题目求助
  • 板块灌水区
  • 楼主ka_da_Duck
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/7/12 19:06
  • 上次更新2024/7/12 19:39:24
查看原帖
东方题目求助
1088058
ka_da_Duck楼主2024/7/12 19:06

我的思路:

把每一组的每一个字符对应存下来,没有的为 0。样例的话就是

A-1 B-0 C-3
A-2 B-0 C-1
A-0 B-3 C-1

把数字组成一个矩阵,并且给每一行(每一个数据)一个编号:

1. 1 0 3
2. 2 0 1
3. 0 3 1

将每两个数据组成的数串匹配。 对与两个数据的每一位上来说,如果有一个是 0 或者他们是相等的就匹配(没出现的可以是任何字符)。所以 2. 和 3. 是匹配的

这个时候,我们将两两匹配的数据之间连一条边,组成一个图。即 2 和 3之间连一条边。

然后,在这个图上,我们找到最大的完全子图(最大团问题),可以用匈牙利算法,但我这里用的是专门解决这个问题的算法(忘了叫啥了,但是正确的)。

我的样例过了,请求哪个大佬救救我了,给个 hack 也行。。。

#include <bits/stdc++.h>

using namespace std;
const int maxn = 1e2 + 10;

int graph[maxn][maxn];
bool nwx[maxn], bestx[maxn];
int bestn;
int n, m, s;

bool place(int x) {
	for (int i = 1; i < x; ++i) 
		if (nwx[i] && !graph[x][i]) return false;
	return true;
}

void backtrack(int x) {
	if (x > n) {
		for (int i = 1; i <= n; ++i) bestx[i] = nwx[i];
		bestn = s;
		return;
	}
	if (place(x)) {
		nwx[x] = 1, s++;
		backtrack(x + 1);
		s--;
	}
	if (s + n - x > bestn) {
		nwx[x] = 0;
		backtrack(x + 1);
	}
}

void Max_Clique() {
	backtrack(1);
	cout << bestn << '\n';
	//for (int i = 1; i <= n; ++i) if (bestx[i]) cout << i << ' ';
}

int N, M;
int f[maxn][maxn];

bool ifMate(int x, int y) {
	for (int i = 1; i <= N; ++i) 
		if (f[x][i] != f[y][i] && f[x][i] != 0 && f[y][i] != 0) return false;
	return true;
}

bool vis[maxn];

signed main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> N >> M;
	string s;
	for (int i = 1, len; i <= M; ++i) {
		cin >> s;
		len = s.size();
		for (int j = 1, x, a; j <= len; ++j) {
			cin >> a;
			x = (s[j - 1] - 'A' + 1);
			f[i][x] = a;
		}
	}
	
	for (int i = 1; i <= N; ++i) 
		for (int j = i + 1; j <= N; ++j) {
			if (!ifMate(i, j)) continue;
			graph[i][j] = graph[j][i] = 1;
		}
	n = N;
//	for (int i = 1; i <= N; ++i) {
//		for (int j = 1; j <= N; ++j) cout << f[i][j] << ' ';
//		cout << '\n';
//	}for (int i = 1; i <= N; ++i) {
//		for (int j = 1; j <= N; ++j) cout <<graph[i][j] << ' ';
//		cout << '\n';
//	}
	Max_Clique();
}
2024/7/12 19:06
加载中...