zoukankan      html  css  js  c++  java
  • 【9505】部落卫队

    Time Limit: 1000ms second
    Memory Limit: 32m 问题描述:
    原始部落byteland中的居民们为了争夺有限的资源,经常发生冲突。几乎每个居民都有他的仇敌。部落酋长为了组织一支保卫部落的队伍,希望从部落的居民中选出最多的居民入 伍,并保证队伍中任何2个人都不是仇敌。
    编程任务:
    给定byteland 部落中居民间的仇敌关系,编程计算组成部落卫队的最佳方案。

    Input

    第1行有2个正整数n和m,表示byteland部落中有n个居民,居民间有m个仇敌关系。居民编号为1,2,…,n。接下来的m行中,每行有2个正整数u和v,表示居民u与居民v是仇敌。 (居民编号为1,2,...,n)

    Output

    程序运行结束时,将计算出的部落卫队的最佳组建方案输出到文件output.txt 中。文件 的第1行是部落卫队的顶人数;文件的第2行是卫队组成xi,1≤i≤n,xi=0表示居民i不在卫队中,xi=1表示居民在卫队中。(第二行数据后都加一空格,最后以回车结束)

    Sample Input

    7 10
    1 2
    1 4
    2 4
    2 3
    2 5
    2 6
    3 5
    3 6
    4 5
    5 6
    
    
    

    Sample Output

    3
    1 0 1 0 0 0 1 
    

    【题解】

    用一个二维数组来表示某个人的所有仇敌关系,a[i][0]表示i号人他的仇敌数量,a[i][1..a[i][0]]则表示这a[i][0]个人具体是谁。

    当我们想要把第i个人放入这个卫队中时,我们先看下现在的卫队中是否有人以他为仇敌。如果没有就放进去。然后我们需要更新这支队伍的仇敌列表,即不能进入这支新队伍的人。在找的时候一边更新最优解就好。

    这题仍然是组合问题,因为1 3 7 和 3 1 7是一样的。所以扫描到x的时候从x+1开始扫描就好。

    【代码】

    在vijos上也有这题P1593,那里有10个数据,平台上只剩2个数据了。

    #include <cstdio>
    
    int n,m,num = 0,max_n = 0;
    int a[1001][1001]; //3MB
    int bo[1001],ans[1001],tt[1001];
    
    void input_data()
    {
        scanf("%d %d",&n,&m);
        for (int i = 1; i <= n;i++)
            for (int j = 1; j<= m;j++) //一开始的初始化 所有人都没有仇敌
                a[i][j] = 0;
        for (int i = 1;i <= m;i++) //增加m个仇敌关系
            {
                int x,y;
                scanf("%d %d",&x,&y);
                a[x][0]++;a[x][a[x][0]] = y; //两个人都各增加一个仇敌 并记录下来
                a[y][0]++;a[y][a[y][0]] = x;
            }
        for (int i = 1;i <= n;i++) //一开始所有人都可以进入这个队伍
            bo[i] = 0;
    }
    
    void sear_ch(int x)
    {
        bo[x] = 1; //这个人入队后直接变成1 之前肯定是0的
        for (int i = 1;i <= a[x][0];i++) //这个人地仇敌,每个仇敌的bo都递增,注意不要直接变成0.比如里面有两个人
            //仇敌都有3。我们这层搜索完后,应该递减,而不是直接变成false,这样bo[3]==1,我们下次就不会把3给加进去了。
            bo[a[x][i]]++;
        ans[++num] = x; //记录答案
        if (num >max_n) //如果大于最大值 就更新解
            {
                max_n = num;
                for (int i = 1;i <= max_n;i++)
                    tt[i] = ans[i];
            }
        for (int i = x+1;i <= n;i++) //从x+1开始 如果可以加入就加入
            if (bo[i] == 0)
                sear_ch(i);
        for (int i = 1;i <=a[x][0];i++)//注意是递减不是直接变成0
            bo[a[x][i]]--;
        bo[x] = 0; //本身是可以直接变成0的,因为bo[x]一开始直接变成1,后来仇敌增加,此外没有涉及到,有也已经递减了。
        num--;
    }
    
    void get_ans()
    {
        for (int i = 1;i <= n;i++)
            sear_ch(i);
        for (int i = 1;i <= n;i++) //根据记录的答案改变各个编号的人的值。最后输出就好
            bo[i] = 0;
        for (int i = 1;i <= max_n;i++)
            bo[tt[i]] = 1;
    }
    
    void output_ans()
    {
        printf("%d
    ",max_n);
        for (int i = 1;i <= n;i++)
            printf("%d ",bo[i]);
    }
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        input_data();
        get_ans();
        output_ans();
        return 0;
    }
    


     

     

  • 相关阅读:
    左孩子右兄弟的字典树
    UVA 1401 Remember the Word
    HDOJ 4770 Lights Against Dudely
    UvaLA 3938 "Ray, Pass me the dishes!"
    UVA
    Codeforces 215A A.Sereja and Coat Rack
    Codeforces 215B B.Sereja and Suffixes
    HDU 4788 Hard Disk Drive
    HDU 2095 find your present (2)
    图的连通性问题—学习笔记
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632439.html
Copyright © 2011-2022 走看看