样例未过求调!二分图染色+背包,玄关
查看原帖
样例未过求调!二分图染色+背包,玄关
996732
Marky_shine楼主2024/8/25 16:22
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100;
int res[N + 5],n,ans,num[N + 5][2],vis[N + 5],g[N + 5][N + 5],dp[N + 5][N + 5],p[N + 5][N + 5],head[N + 5],sum;
vector<int> G[N + 5][2];
void dfs (int x,int fa,int color){
	num[sum][head[x] = color] ++;
	G[sum][color].push_back (x);
	for (int i = 1;i <= n;i ++){
		if (!g[i][x] && i != fa && x != i){
			if (head[i] == -1) dfs (i,x,color ^ 1);
			else if (head[i] == color){
				puts("No solution");
				exit(0);
			}
		}
	}
}
signed main(){
	cin >> n;
	for (int i = 1;i <= n;i ++){
		int v = -1;
		while (v != 0){
			cin >> v;
			g[i][v] = 1;
		}
	}
	for (int i = 1;i <= n;i ++)
		for (int j = i + 1;j <= n;j ++)
			if (!(g[i][j] && g[j][i]) && (g[i][j] || g[j][i])) g[i][j] = g[j][i] = 0;
	memset (head,-1,sizeof head);
	for (int i = 1;i <= n;i ++){
		if (head[i] == -1){
			sum ++;
			dfs (i,0,1);
		}
	}
	dp[0][0] = 1;
	for (int i = 1;i <= sum;i ++){
		for (int j = 0;j <= n / 2;j ++){
			int t = j - num[i][0];
			if (t >= 0 && dp[i - 1][t]) dp[i][j] = 1,p[i][j] = 0;
			t = j - num[i][1];
			if (t >= 0 && dp[i - 1][t]) dp[i][j] = 1,p[i][j] = 1;
		}
	}
	for (int i = n / 2;i >= 0;i --){
		if (dp[sum][i]){
			ans = i;
			break;
		}
	}
	int t = ans;
	for (int i = sum;i > 0;i --){
		for (int j = 0;j < G[i][p[i][t]].size();j ++)
			vis[res[++ res[0]]] = G[i][p[i][t]][j] = 1;
		t -= num[i][p[i][t]];
	} 
	sort (res + 1,res + res[0] + 1);
	cout << res[0] << " ";
	for (int i = 1;i <= res[0];i ++) cout << res[i] << " ";
	cout << endl << n - res[0] << " ";
	for (int i = 1;i <= n;i ++)
		if (!vis[i]) cout << i << " ";
	return 0;
}
2024/8/25 16:22
加载中...