部落卫队

题目描述

原始部落byteland中的居民们为了争夺有限的资源,经常发生冲突。几乎每个居民都有他的仇敌。部落酋长为了组织一支保卫部落的队伍,希望从部落的居民中选出最多的居民入伍,并保证队伍中任何2 个人都不是仇敌。

给定byteland部落中居民间的仇敌关系,编程计算组成部落卫队的最佳方案。

输入输出格式

输入格式:

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

输出格式:

第1行是部落卫队的人数;文件的第2行是卫队组成x i,1≤i≤n,xi =0 表示居民i不在卫队中,xi=1表示居民i在卫队中。

输入输出样例

输入样例#1: 复制
7  10
1  2
1  4
2  4
2  3
2  5
2  6
3  5
3  6
4  5
5  6
输出样例#1: 复制
3
1 0 1 0 0 0 1

说明

60%数据:n<=20,m<=100

所有数据:n<=100,m<=3000

思路:深搜,注意加一个最优性剪枝,如果当前已经选的人数加上剩下所有人都小于目前的ans,那显然不可能优于当前结果。

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i <= (b); ++ i)
#define REP(j, a, b) for(int j = (a); j <= (b); ++ j)
#define PER(i, a, b) for(int i = (a); i >= (b); -- i)
using namespace std;
template <class T>
inline void rd(T &ret){
    char c;
    ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9'){
        ret = ret * 10 + (c - '0'), c = getchar();
    }
}
int n,m,link[106][106],tmp[106],ans,f[106];
void dfs(int cur,int tot){
     if(cur==n+1){
         if(tot>ans){
             ans=tot;
             REP(i,1,n)f[i]=tmp[i];
         }
         return;
     }
     if(tot+n-cur+1<=ans)return;
     bool conflict=false;
     REP(i,1,cur-1){
         if(tmp[i]&&link[cur][i]){
             conflict=true;
             break;
         }
     }
     if(!conflict){
         tmp[cur]=1;
         dfs(cur+1,tot+1);
         tmp[cur]=0;
     }
     dfs(cur+1,tot);
}
int main(){
    rd(n),rd(m);
    REP(i,1,m){
        int a,b;
        rd(a),rd(b);
        link[a][b]=link[b][a]=1;
    }
    dfs(1,0);
    cout<<ans<<endl;
    REP(i,1,n)cout<<f[i]<<' ';
    return 0;
}
原文地址:https://www.cnblogs.com/czy-power/p/10418010.html