3967. Counting Friends ##
Description
FJ 的N 头奶牛(2<= N<= 500)都加入了社交网络“哞不可” 。
每头奶牛有一个或多个与它们自己在哞不可上互相关注的朋友。为了好玩,FJ 制作了一个列表,记下每头奶牛的朋友数目。但是,在书写列表的过程中,农夫John 惆怅了,以至于他错误地写下了一个额外的数字(因此他的列表包含N + 1 个数字,非他预计的N 个数字)。
请帮助FJ 找出在他的列表中有哪些数字可以是那个错误的额外数字。
Input
第一行:整数N。
第2 至N + 2 行:第i + 1 行包含FJ 的某一头奶牛的朋友数量,或者也许是那个错误的额外数字。
Output
第一行:一个整数K 给出在FJ 的列表中有多少项目可能是那个额外的数字(或者,K = 0 意味着没有一个数字,移除后可以产生一个可行的朋友配对)。
第2 至K + 1 行:每行包含可能是额外的数字按照输入顺序产生的序号(1到N +1)——也就是说,一个移除后,剩下的N 个数字符合奶牛们某一个可行
的朋友关系集合。这K 行的序号须按从小到大排列。
Sample Input
4
1
2
2
1
3
Sample Output
3
1
4
5
样例解释:
FJ 有4 头奶牛。两头每头只有一个朋友,两头各有两个朋友,还有一头有三个朋友(当然,这些数字其中一个是额外的并且不属于这个列表)。
移除FJ 列表的第一个数字(数字1)之后会得到一个剩下的数字2,2,1,3 组成的列表,并且符合一个可行的朋友关系配对——例如,如果我们将奶牛从A
到D 命名,那么配对(A;B); (A;C); (A;D) 以及(B;C) 就足够了,这是因为A有三个朋友,B 和C 都各有两个朋友,还有D 有一个朋友。同理,从FJ 的列表里移除另外一个“1”也是可行的,还有移除“3”也可以。从FJ 的列表里移除任意一个“2”都不可——我们可以看到剩下数字的和是奇数,明显我们无法凑出一个对应的配对。
Data Constraint
对于9% 的数据,N <=10。
对于27% 的数据,N <=100。
分析:枚举每个数判断是否可能为额外的数字,至于判断的过程就是把所有数从大到小排序,然后往后减即可,如果有一个数减不完,说明不可行,要用归并排序,快排显然超时。
代码
#include <cstdio>
#include <algorithm>
#define N 600
using namespace std;
struct arr
{
int v,num;
}a[N];
int b[N],x[N],n;
void merge(int st,int en)
{
int l=st;
int i=st;
int j=en+1;
int b1[N]={0};
for (int ii=st;ii<=n;ii++)
{
b1[ii]=b[ii];
b[ii]=0;
}
while (i<=en&&j<=n)
{
if (b1[i]>b1[j]) b[l++]=b1[i++];
else b[l++]=b1[j++];
}
for (int k=i;k<=en;k++)
b[l++]=b1[k];
for (int k=j;k<=n;k++)
b[l++]=b1[k];
}
int cmp(arr x,arr y)
{
return x.v>y.v;
}
int main()
{
scanf("%d",&n);
int sum=0;
for (int i=1;i<=n+1;i++)
{
scanf("%d",&a[i].v);
a[i].num=i;
sum+=a[i].v;
}
int cnt=0;
sort(a+1,a+n+2,cmp);
for (int i=1;i<=n+1;i++)
{
int p=0,ls=1;
bool fl=false;
if ((sum-a[i].v)%2==1) continue;
for (int j=1;j<=n+1;j++)
if (i!=j) b[++p]=a[j].v;
for (int j=1;j<=n;j++)
{
merge(j,ls);
for (int k=j+1;k<=n;k++)
if (b[k])
{
b[k]--;
b[j]--;
ls=k;
if (!b[j]) break;
}
if (b[j])
{
fl=true;
break;
}
}
if (!fl) x[++cnt]=a[i].num;
}
sort(x+1,x+cnt+1);
printf("%d\n",cnt);
for (int i=1;i<=cnt;i++)
printf("%d\n",x[i]);
}