洛谷 2244
Posted TSOI_Vergil
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 2244相关的知识,希望对你有一定的参考价值。
这道题有很巧妙的结论,但还是难以掩盖它是乱搞题的本质-----By APT
这道题看起来无从下手,因为关系很复杂,我先给出做法,再给出证明,首先我们将A赢B的关系表示成A-->B的有向边,我们找到出度最大的点,然后找到没有被它直接指向的点,然后这些点都是可能赢的点,我们将它们标记为能赢,然后放入队列,继续上述操作,最终就能得到答案。
证明:首先由于我们一开始的点是出度最大点,也就是说没有其他点能够一下打败当前点和当前点能直接打败的点,因为如果存在这样的点,它的度数一定大于当前点。那么这样又如何呢?我们考虑剩下的所有点,为什么它们都可能赢呢,因为我们可以构造出一种方式令它们胜利,对于一个剩下的点,我们先让别的点都输掉,然后在让当前点把它能直接打败的点全打败,最后再让这个剩下的点打败当前点,于是它就赢了,然后我们对于每个能赢的点做这种操作,剩下的点都是可能打败当前能赢的点的点,我们先让能赢的点把其他点全打败,再让这个点打败能赢的点,这样它也能赢。于是我们这样一直推下去就可以了。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 1000005
int que[maxn+5],next[maxn],prev[maxn];
int pre[maxn],last[maxn],other[maxn],cd[maxn],l;
int n,m,cnt;
bool flag[maxn],ans[maxn];
int read(void)
char ch=getchar();
int x=0;
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9')
x=x*10+ch-'0';
ch=getchar();
return x;
void connect(int x,int y)
l++;
pre[l]=last[x];
last[x]=l;
other[l]=y;
int main()
//scanf("%d",&n);
n=read();
for (int i=1;i<=n;i++)
//scanf("%d",&cd[i]);
cd[i]=read();
for (int j=1;j<=cd[i];j++)
int a;
//scanf("%d",&a);
a=read();
connect(i,a);
if (cd[i]>cd[que[1]]) que[1]=i;
for (int i=0;i<=n;i++) prev[i]=i-1;next[i]=i+1;
next[n]=0;pre[0]=0;
int h=0,t=1;
while (h!=t)
h=h%maxn+1;
int u=que[h];
for (int p=last[u];p;p=pre[p])
int v=other[p];
flag[v]=1;
int w=next[0];
while (w)
if (!flag[w])
ans[w]=1;
cnt++;
next[prev[w]]=next[w];
prev[next[w]]=prev[w];
t=t%maxn+1;
que[t]=w;
w=next[w];
for (int p=last[u];p;p=pre[p])
int v=other[p];
flag[v]=0;
printf("%d",cnt);
for (int i=1;i<=n;i++)
if (ans[i]) printf(" %d",i);
printf("\\n");
return 0;
以上是关于洛谷 2244的主要内容,如果未能解决你的问题,请参考以下文章