zoukankan      html  css  js  c++  java
  • 文理分班[二分图]

    文理分班[二分图]

    题目描述

    jzyz每年的文理分班的时候,每个班都会有一些同学分到其他班,还会进入一些其他班的同学进入这个班。

    小x负责安排座位,为了照顾分班带来的那种伤感情绪,小x制定了很人性化的座位安排计划,具体计划如下:

    比如AB都是本班学生且是好朋友,A分到了其他班,而C则是外班进入这个班的,CA并不熟悉,而CB关系很好,那么小x为了照顾AC的情绪,就会让B坐在A的位置,C坐在B的位置。

    当然,实际情况可能很复杂,比如一个班里的同学之间关系不一定好,外班进来的可能和本班很多人关系都很好。

    现在告诉你,和小x所在班有关系的人一共有n个人,小x想知道有没有一个合理的方案来满足自己的座位安排计划。

    输入格式

    本题为多组数据,第一行一个整数M,表示有M组测试数据。

    对于每组测试数据,每组的第一行一个整数n,表示一共有n个人和这个班有关系。

    接下来一行n个整数,第i个整数表示第i个人是否是本班学生(0表示不是,1表示是,分到其他班的也算是本班学生)

    接下来一行n个整数,第i个整数表示第i个人是否要分到其他班(0表示留在本班,1表示分到其他班,如果第i个人是由外班分进来的,那么第i个整数就是一个随机整数,没有实际意义)

    接下来是一个nn列的一个二维矩阵,第i行第j列的数表示第i个人和第j个人是否关系很好(1表示认识,0表示不认识),对角线上是0,但是自己肯定认识自己。

    输出格式

    每组数据,如果存在一个方案,输出 “_”(不含引号)。

    如果没有方案,输出 “T_T”(不含引号)。都是半角字符。

    样例

    样例输入

    1
    3
    1 1 0
    0 1 0
    0 1 1
    1 0 0
    1 0 0
    

    样例输出

    ^_^
    

    思路

    首先diss出题人, 把话说清楚能死? 阅读理解也没宁这么出的

    "n个人和这个班有关系。" 在这的意思是, 不是本班的学生一定会分来本班, 因为他和这个班有联系

    小x要管的人, 只包括本班教室里的人 (没有被分走的本班学生和分进来的外班学生)

    明确了题意,我们来解释一下样例的3,4行

    1 1 0
    0 1 0
    

    第一个人:是本班学生, 没有分走

    第二个人:是本班学生,但被分到了外班

    第三个人:不是本班学生, 一定会分来本班, 第二行的 0 只是一个随机整数, 而不是代表他留在自己的班

    好了!只要你搞清楚题意, 这道题就是个板子 (出题人我谢谢宁全家)

    考虑一下哪些人可以相互换坐

    1. 自己是本班学生, 没被分走, 自己可以坐在自己的座位上(和自己换坐)
    2. 某个人和本班的一个学生是朋友, 他们两个就可以换坐(即使本班的这个学生被分走, 他的座位还留在本班教室)

    对小x需要管的人跑一边匈牙利, 如果一个人找不到可以换坐的, 就可以直接break了

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    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]){
                vis[i] = 1;
                if(!match[i] || find(match[i])){
                    match[i] = u;
                    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;//i和j很熟, 且j是本班的(即使j被分到外班,j的座位还在本班)
                }
            }
            bool flag = 0;
            for(int i=1; i<=n; i++){
                memset(vis,0,sizeof(vis));
                if((!a[i]) || (a[i]&&!b[i])){//没有被分走的本班学生和分进来的外班学生
                    if(!find(i)){//找不到可以换坐的人
    					flag=1;
    					break;
                    }
                }
            }
            printf("%s
    ", flag ? "T_T" : "^_^");
        }
        return 0;
    }
    
  • 相关阅读:
    永久修改cmd字体、大小、编码
    Linux总结--vi与vim
    VBox配置虚拟机固定IP可上网
    Redis之三--数据类型
    Linux常用小命令
    Redis之二--单节点搭建
    Linux二
    Java 基础类之三
    Java 基础类之二
    JAVA语言的基本元素:类和对象
  • 原文地址:https://www.cnblogs.com/hzoi-poozhai/p/12878731.html
Copyright © 2011-2022 走看看