首页 > 其他分享 >文理分班

文理分班

时间:2024-05-11 17:22:40浏览次数:11  
标签:int res flow 文理 edge maxn 分班 dis

en,被JD大佬强行思考了一下建图,趁着记得,写一篇题解

注:前面二分图解法,后面网络流解法

题目

image

二分图解法

提前处理好位置与人的关系,跑匈牙利算法,注释在代码上

题解
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1050;
int n,k,m,vis[maxn],match[maxn],ans,g[maxn][maxn],a[maxn],b[maxn];
int find(int u){
    for(int i=1;i<=n;i++){
        if(g[u][i]&&!vis[i]){//u这个位置能坐i这个人且i这个人没坐其他位置 
            vis[i]=1;
            if(!match[i] || find(match[i])){//如果这没人,或这个位置有其他人可以 
                match[i] = u;//i可以坐这个位置 
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    scanf("%d",&m);
    while(m--){
        memset(g,0,sizeof(g));
        memset(match,0,sizeof(match));//初始化 
        scanf("%d", &n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
		{ 
            scanf("%d",&b[i]);
            if(a[i]==1&&b[i]==0) g[i][i]=1;//本班人能坐自己位置 
        }
        for(int i=1;i<=n;i++)
		{
            for(int j=1;j<=n;j++)
			{
                int x;scanf("%d",&x);
                if(x==1&&a[j]==1) g[i][j]=1;//j可以坐在i这个位置 
            }
        }
        bool flag=0;
        for(int i=1;i<=n;i++){
            memset(vis,0,sizeof(vis));
            if((!a[i]) || (a[i]&&!b[i])){//i这个人是外班的或分班前后依旧是本班的人都需要找个位置 
                if(!find(i)){
					flag=1;//有人没座,break 
					break;
                }
            }
        }
        printf("%s\n",flag?"T_T":"^_^");
    }
    return 0;
}

网络流解法

\(S\) 向每个座位连边,座位向能坐座位的人连边,人像 \(T\) 连边,边权均为一,最大流即为能找到座位的人数,与总座位数比较

即可,注意细节和上面二分图解法细节一致

题解——代码来自JD大佬
#include <bits/stdc++.h>
#define N 100005
#define inf 1e5

using namespace std;

int n,m,S,T,dis[N],sum,a[N],b[N],c[55][55],Q;
queue < int > q;

struct Edge{int next,to,dis,flow;}edge[N];
int head[N],now[N],cnt = 1;
void add(int from,int to,int dis){
	edge[++cnt] = (Edge){head[from],to,dis,0};
	head[from] = cnt;
}

void Input(){
	memset(head,0,sizeof(head));cnt = 1;
	scanf("%d",&n);S = 0,T = 2 * n + 1,sum = n;
	for(int i = 1;i <= n;i ++) scanf("%d",&a[i]);
	for(int i = 1;i <= n;i ++) {scanf("%d",&b[i]);if(a[i] == 1 and b[i] == 1) sum --;}
	for(int i = 1;i <= n;i ++) for(int j = 1;j <= n;j ++) scanf("%d",&c[i][j]);
	for(int i = 1;i <= n;i ++){
		for(int j = 1;j <= n;j ++){
			if((c[i][j] == 1 or i == j) and a[i] == 1) add(i,j + n,1),add(j + n,i,0); 
		}
	} 
	for(int i = 1;i <= n;i ++) if(a[i] == 1) add(S,i,1),add(i,S,0);
	for(int i = 1;i <= n;i ++) if(a[i] == 0 or b[i] == 0) add(i + n,T,1),add(T,i + n,0); 
}

bool bfs(){
	for(int i = S;i <= T;i ++) dis[i] = 0;
	dis[S] = 1,q.push(S);
	while(!q.empty()){
		int x = q.front();q.pop();
		now[x] = head[x];
		for(int i = head[x];i;i = edge[i].next){
			int y = edge[i].to;
			if(!dis[y] and edge[i].dis > edge[i].flow){
				dis[y] = dis[x] + 1;
				q.push(y);
			}
		}
	}
	return dis[T];
}

int dfs(int x,int flow){
	if(x == T or !flow) return flow;
	int res = 0;
	for(int i = now[x];i;i = edge[i].next){
		now[x] = i;
		int y = edge[i].to,d;
		if(dis[y] == dis[x] + 1 and (d = dfs(y,min(edge[i].dis - edge[i].flow,flow - res)))){
			edge[i].flow += d,edge[i ^ 1].flow -= d;
			res += d;if(res == flow) break;
		}
	}
	return res;
}

void work(){
	int ans = 0;
	while(bfs()) ans += dfs(S,inf);
	if(ans == sum) puts("^_^");
	else puts("T_T");
}

signed main(){scanf("%d",&Q);while(Q --){Input();work();}return 0;}

标签:int,res,flow,文理,edge,maxn,分班,dis
From: https://www.cnblogs.com/oceansofstars/p/18186830

相关文章

  • 【华为OD机试】真题B卷-分班问题(JAVA)
    华为OD机试真题汇总目录  【华为OD机试】真题汇总A+B+C+D券(Python实现)  【华为OD机试】真题汇总A+B+C+D卷(JAVA实现)  【华为OD机试】真题汇总A+B+C+D卷(C++实现)一、题目题目描述:幼儿园两个班的小朋友在排队时混在了一起,每位小朋友都知道自己是否与前面一位小......
  • 一文理解什么是DevOps,通俗易懂白话文
    一文理解什么是DevOps,通俗易懂白话文 devops是什么❝DevOps维基百科定义DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、......
  • D2-浦语·灵笔图文理解创作 Demo
    这里我使用InternStudio中的A100(1/4)*2机器和internlm-xcomposer-7b 模型部署一个图文理解创作Demo。一、环境准备选择A100(1/4)*2的配置:我的开发机列表:打开刚刚租用服务器的进入开发机,并在终端输入 bash 命令,进入 conda 环境,接下来就是安装依赖。进入 conda 环境......
  • 湖北文理学院 计算机工程学院
    专业介绍 计算机科学与技术【培养目标】培养目标:培养具有良好科学文化素养和社会责任感,系统掌握计算机科学理论和专业知识,了解计算机前沿技术,能够分析、设计和开发较为复杂的计算机应用系统,具备创新意识、国际化视野和团队合作精神,能够在互联网、大数据和人工智能等领域从事......
  • 湖北文理学院 电子信息硕士
    培养方向:计算机技术软件工程  培养单位:计算机工程学院湖北文理学院电子信息专业硕士学位授权点依托计算机工程学院,设有计算机技术和软件工程两个领域,计算机技术领域主要服务于电子信息及相关产业,在信息系统的设计开发、大数据与云计算、嵌入式系统及智能网联技术研发等方面......
  • 计算机与电气学院 文理
    自动化专业介绍(湖南省一流本科专业建设点,工程教育专业认证受理专业)自动化专业(理工类)(专业代码 080801)是以自动控制理论为主要理论基础,以电子技术、计算机信息技术、传感器与检测技术、嵌入式技术等为主要技术手段,对各种自动化装置和系统实施控制的一门专业。培养德、智......
  • 基于SpringBoot+Vue的文理医院预约挂号系统设计实现(源码+lw+部署文档+讲解等)
    (文章目录)前言:heartpulse:博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌:heartpulse:......
  • P4313 文理分科
    题意给定一个\(n*m\)的矩阵。你需要将其中每一个元素分成两个集合。当一个元素的集合为\(A\),获得\(a_{i,j}\)。集合为\(B\),获得\(b_{i,j}\)。当一个元素与她相邻的所有元素都在同一个集合,获得\(c_{i,j}\)或\(d_{i,j}\)的贡献。Sol最小割。我们先将答案加上......
  • 分班排列准考证列表
    问题:准考证号和班级两列,按班级分成若干列解决:第一步:新建一个工作表,在A1和B1分别输入“准号证号”和“班级”,C1输入数字1第二步:选取A1:C1,向右填充至AS1第三步:选取A2,输入以下公式:=FILTER(数据源!$A:$B,数据源!$B:$B=C1)第四步:选取A2:C2,向右填充至AS2 ......
  • 测试技能提升篇——一文理解消息中间件里那些通用的核心概念
    我们测试同学在实际工作中或多或少都会接触过ActiveMQ、RabbitMQ,Kafka,和RocketMQ这类消息中间件产品,不同的公司会选择不同的产品,大家可能会觉得产品比较多,了解起来有些复杂!其实无论使用哪种中间件产品,他们的核心功能都是比较类似的。本文就不来汇总一下中间件产品的核心概念,给大家......