P1285 队员分组(二分图&背包)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1285 队员分组(二分图&背包)相关的知识,希望对你有一定的参考价值。
P1285 队员分组(二分图&背包)
建边改为不认识的两人连边。
然后会形成若干个连通块。
对每个连通块进行二分图染色。
若有连通块不能完全染色肯定无解。
否则相当于每个连通块有两种选择方式:选黑点到第一组,否则选白点到第2组。预处理每个连通块的黑点和白点。
显然是个判断性背包问题。
令 d p [ i ] [ j ] dp[i][j] dp[i][j]对于前 i i i个连通块第一组个数为 j j j是否可行,为了输出方案还需要维护个 o p [ i ] [ j ] op[i][j] op[i][j]记录第 i i i个连通块是选择黑点还是白点。
时间复杂度: O ( C n ) , C O(Cn),C O(Cn),C是连通块个数。
// Problem: P1285 队员分组
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1285
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-08-27 16:07:42
// --------by Herio--------
#include <cstdio>
#include <cctype>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 128;
//if have char input #define should cancel
#define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
template <typename T>
inline T& read(T& r) {
r = 0; bool w = 0; char ch = getchar();
while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
return r = w ? -r : r;
}
vector<int> G[maxn],vec[maxn][2],ans[2];
inline void addedge(int from,int to){G[from].push_back(to);}
int n,tmp[maxn][maxn],f[maxn][maxn],opt[maxn][maxn],vis[maxn],col[maxn],vec_tot;
inline bool bfs(int s){
queue<int> Q;Q.push(s);vis[s] = 1;
vec_tot++;
while(!Q.empty()){
int u = Q.front();Q.pop();
vec[vec_tot][col[u]].push_back(u);
for(int v : G[u])
if(!vis[v])col[v] = col[u] ^ 1,vis[v] = 1,Q.push(v);
else if(col[v] == col[u])return false;
}
return true;
}
inline void solve(){
read(n);
for(int u = 1,v;u <= n;u++){
while(1){
read(v);if(!v) break;
tmp[u][v] = 1;
}
}
for(int u = 1;u <= n;u++)
for(int v = u + 1;v <= n;v++)
if(!(tmp[u][v] && tmp[v][u]))addedge(u,v),addedge(v,u);
for(int i = 1;i <= n;i++)
if(!vis[i] && !bfs(i)){
puts("No solution");
return;
}
f[0][0] = 1;
for(int i = 1;i <= vec_tot;i++)
for(int j = 0;j <= n;j++){
if(j >= vec[i][0].size() && f[i - 1][j - vec[i][0].size()])f[i][j] = 1,opt[i][j] = 0;
if(j >= vec[i][1].size() && f[i - 1][j - vec[i][1].size()])f[i][j] = 1,opt[i][j] = 1;
}
int now;
for(int i = n >> 1;i >= 0;i--)
if(f[vec_tot][i]){now = i;break;}
for(int i = vec_tot;i >= 1;i--){
for(auto x : vec[i][opt[i][now]])ans[0].push_back(x);
for(auto x : vec[i][opt[i][now] ^ 1])ans[1].push_back(x);
now -= vec[i][opt[i][now]].size();
}
sort(ans[0].begin(),ans[0].end());
sort(ans[1].begin(),ans[1].end());
printf("%d ",(int)ans[0].size());
for(auto x : ans[0])printf("%d ",x);
putchar('\\n');
printf("%d ",(int)ans[1].size());
for(auto x : ans[1])printf("%d ",x);
putchar('\\n');
}
int main(){
solve();
}
以上是关于P1285 队员分组(二分图&背包)的主要内容,如果未能解决你的问题,请参考以下文章
二分图匹配入门专题1I - Hiding Gold light oj 1152二分图匹配-------------------我是终于不那么水的水题分割线------------------(代码片
CF1354E Graph Coloring(构造二分图+背包)
CF-1354 E. Graph Coloring(二分图,背包,背包方案输出)
HDU-1561 The more, The Better (树形DP+分组背包)