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; }