codeforces 1019C. Sergey's problem

简述题意:一张无自环的有向图,请找出一个点集Q,满足Q内的点互相没有边,且Q内的点一定可以通过1次或2次移动,到达Q集合以外的任意一个点。

time limit per test 2 seconds

memory limit per test256 megabytes

算法:玄学思路

难度:NOIP

题解:两次for循环找出答案!

  1. 第一层for循环:从小到大枚举点的编号,将与此点相连的点打上标记,这样就维护了现在的点集Q中的点通过一次移动可以到达任意点集Q以外的点,且所选点集Q中编号小的点与编号大的点之间没有连边。
  2. 第二层for循环:从大到小枚举点的编号,这次循环删除了编号大的到编号小的点之间的边,然后就可以严格保证点集内部没有边了。

这时,我们考虑另一个约束条件: 点集Q内的点通过1次或2次移动,到达Q集合以外的任意一个点!

 我们现在可以发现,对于已经删除你的点,我们可通过将它删除的那个点到达它及与它相连的不在点集中的点(满足  1<=移动次数<=2)

 

代码如下:

#include <bits/stdc++.h>
#define ll long long
#define N 1000007
using namespace std;
int n,m,vis[N],cnt;
vector<int>V[N];

int main() 
{
    scanf("%d%d",&n,&m);
    int x,y;
    for(int i = 1;i <= m;i++)
    {
    	scanf("%d%d",&x,&y);
    	V[x].push_back(y);
    }
    for(int i = 1;i <= n;i++) 
    {
    	if(!vis[i]) 
    	{
            vis[i]=1;
            for(auto v : V[i]) //C++11,请食用
            {
            	if(!vis[v]) vis[v]=-1;
            }
    	}
    }
    for(int i = n;i >= 1;i--) 
    if(vis[i]==1) 
    {
        cnt++;
        for(auto v : V[i]) vis[v]=-1;//C++11,请食用
    }
    printf("%d\n",cnt);
    for(int i = 1;i <= n;i++)
    {
    	if(vis[i]==1) printf("%d ",i);
    }
    puts("");
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值