选举预测 Ele

来源:互联网 发布:小说 章节 数据库设计 编辑:程序博客网 时间:2024/05/17 04:01

选举预测

(ele.pas/c/cpp/in/out,1s,64MB)

题目描述

科学院的领袖Dunkelheit 的任期,随着局势的平复很快就要结束了。于是,这次具有非凡意义的科学院新领袖的选举很快就要开始了。
选举的第一步是辩论赛。它的规则是这样的:如果当前剩下的候选人多于2 人,那么就从中任选2 人进行辩论。输者退出比赛,胜利者继续留在比赛中,如此直到只剩下一个候选人,他就取得了辩论赛的胜利。辩论赛的胜者在后面的选举中将会更占优势,所以说人们都很关注这次比赛的结
果,历史学家Geheimnis 也不例外。他收集了所有N 个候选人的资料,发现如果两个候选人以前曾经比赛过,那么这两个人再次比赛的时候比赛结果是很难改变的(可以认为是不可能)。按照Geheimnis 掌握的情报,你需要帮助他判断那些候选人有可能取得胜利。

输入格式

第一行包含一个正整数N,表示候选人的数目。
之后 N 行,候选人从1 开始编号,第(i + 1)行描述第 i 个候选人。第一个数为K,后面K 个编
号,表示候选人 i 之前赢过的候选人。

输出格式

输出一行。第一个数为C,表示有C 个候选人有可能取得胜利;之后C 个数表示他们的编号。

样例输入

4
2 2 3
0
1 2
1 2

样例输出

3 1 3 4

数据范围与约定
对于50% 的数据,N200
对于 100% 的数据,N106,胜负关系不会超过106 对。


对一个人A,对于所有能赢A的人B,只要存在另一个人C,B不一定能赢C,且C不一定能赢A,则A就有可能获胜。

考试的时候我的做法是开邻接矩阵,对每个人判断一次,能得50分。Fancy学姐对这种思路种种stl魔改之后过了,不过比较慢,最大的点用了0.5秒。

正解思路:

  • 只要一个已经确定有可能赢的人A不一定能赢B,则B有可能赢;出度最大的一个或几个人一定有可能赢,因为假设存在一个人一定能打败他,那么此人一定要能够打败他打败的所有人,此时我们假设的这个人入度比他还大,自相矛盾,假设不成立
  • 开一个队列存已经确定有可能赢的人,用一个链表(可以用数组模拟)存不确定的人
  • 用队列里的人更新链表,确定有可能赢的人入队并在链表中删除
  • tot记录有可能赢的人数、win[i]表示第i个人有没有可能赢,输出即可

#include<iostream>#include<algorithm>#include<cstdio>#include<queue>using namespace std;const int N=1000010;int n,num[N];//num:第i个人战胜的人数struct node{int to,next,u;}e[N];int head[N],ecnt;void add(int u,int v){e[++ecnt].u=u;e[ecnt].to=v;e[ecnt].next=head[u];head[u]=ecnt;}queue<int> que;bool win[N];int tot=0;int pre[N],ne[N];void del(int i){int l=pre[i],r=ne[i];ne[l]=r,pre[r]=l;}void bfs(){    while(!que.empty())    {        int x=que.front();que.pop();        int j=head[x];        for(int i=pre[n+1];i;i=pre[i])        {            while(i<e[j].to)                j=e[j].next;            if(i!=e[j].to)            {                tot++;                que.push(i);                win[i]=1;                del(i);            }        }    }}int main(){    freopen("ele.in","r",stdin);    freopen("ele.out","w",stdout);    cin>>n;    int maxnum=0;    for(int i=1;i<=n;++i)        pre[i]=i-1,ne[i]=i+1;    pre[n+1]=n;    ne[0]=1;    for(int i=1,a=0,b;i<=n;++i)    {        scanf("%d",&num[i]);        if(num[i]>maxnum)            maxnum=num[i];        for(int j=1;j<=num[i];++j)        {            scanf("%d",&b);            add(i,b);        }    }    for(int i=1;i<=n;++i)        if(num[i]==maxnum)        {            tot++;            que.push(i);            win[i]=1;            del(i);        }    bfs();    printf("%d ",tot);    for(int i=1;i<=n;++i)        if(win[i])            printf("%d ",i);    return 0;}
0 0
原创粉丝点击