题解 P3068 【[USACO13JAN]派对邀请函Party Invitations】
既然不好写就换一个思路
这道题如果按每一小块直接算,既麻烦又费时,所以我们可以转换一下思路
我们可以把所有的数据接到一起,用一个算前缀和的数组进行标号,在每一次循环有效的处理每一组数据
#include<bits/stdc++.h>
using namespace std;
int n,g,sum[2050],t[2050],a[250005],ans=1;
bool f[250005];//定义
int main()
{
f[1]=1;
scanf("%d%d",&n,&g);
for(int i=1;i<=g;i++)
{
scanf("%d",&t[i]);//输入每组大小
sum[i]=sum[i-1]+t[i];//记录总数
for(int j=sum[i-1]+1;j<=sum[i];j++)
scanf("%d",&a[j]);//在每一小段输入每个
}
while(1)//多次循环一直找
{
int k=ans;//继承上一次循环结果
for(int i=1;i<=g;i++)
{
int q,s=0;//清零
for(int j=sum[i-1]+1;j<=sum[i];j++)//枚举每一段
{
if(f[a[j]])//是否参加
s++;
else
q=a[j];//标记
}
if(t[i]-s==1)//至少k-1个奶牛参加派对时,必须邀请最后的一头奶牛
{
f[q]=1;//参加
ans++;//总数加上这个
}
}
if(k==ans)//两次循环结果不再变化,则已最优
{
cout<<ans;//输出
return 0;
}
}
}