zoukankan      html  css  js  c++  java
  • 题解 P1285 【队员分组】

    题目链接

    Solution 队员分组

    题目大意:每个都有一些认识的,(A)认识(B)不一定有(B)认识(A),你要把所有的人分成两个队伍,要求同一队伍内的人必须两两认识,在这前提上使得两队的人数尽量接近,求分组方案

    二分图,背包


    分析:必须两两认识不好处理,我们可以把不认识的人连上边,这样就变成了同一队伍内的人之间没有边了

    我们发现在这种情况下不同连通分量的人互不影响因此可以分别计算

    对于连通分量内的点,我们要把它黑白染色,并且同一颜色的点之间没有边,这就是二分图的定义,我们一次(bfs)就可以做到,并且如果任意连通分量无解则整个问题无解

    然后使得两个队伍的人数接近,我们发现一个连通分量的黑点可以有两种情况,因此我们跑一个布尔背包,从(n/2)枚举求一下能不能拼出(x)个黑点就可以了

    毒瘤的双倍经验题

    #include <cstdio>
    #include <cctype>
    #include <vector>
    #include <queue>
    #include <algorithm>
    using namespace std;
    const int maxn = 128;
    inline int read(){
    	int x = 0;char c = getchar();
    	while(!isdigit(c))c = getchar();
    	while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    	return x;
    }
    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(){
    	n = read();
    	for(int u = 1,v;u <= n;u++)
    		while((v = read()))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('
    ');
    	printf("%d ",(int)ans[1].size());
    	for(auto x : ans[1])printf("%d ",x);
    	putchar('
    ');
    }
    int main(){
    	solve();
    }
    
  • 相关阅读:
    数据类型(列类型-小数型)
    Python全栈开发之2、数据类型-数值、字符串、列表、字典、元组和文件处理
    Python全栈开发之3、深浅拷贝、变量和函数、递归、函数式编程、内置函数
    Python全栈开发之1、python基础初识介绍以及安装
    数据类型(列类型)
    中文数据问题
    SQL--数据--基本操作
    SQL--数据表--基本操作
    SQL--数据库--基本操作
    Mysql数据库
  • 原文地址:https://www.cnblogs.com/colazcy/p/11792411.html
Copyright © 2011-2022 走看看