Codeforces1019C

Codeforces1019C


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

做法:思路神奇。做法就是编号小到大枚举选的点,然后把比他大的后继删除,再从大到小枚举,继续删除这被选中的点中互相有边的情况。正确性可以这么考虑,第一次选出的点保证了现在的点集通过一次移动即可到达任意其余的点,且所选点集中编号小的点与编号大的点之间没有边。第二次删除了编号大的到编号小的点之间的边,现在已经保证点集内部没有边了,考虑删除的点,我们可通过将他删除的那个点到达它及与它相连的不在点集中的点。

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define pb push_back
typedef long long ll;
const int N = 1e6 + 7;
using namespace std;
int n,m,vis[N],cc;
vector<int> G[N];

int main() {
    scanf("%d%d",&n,&m);
    int x,y;
    rep(i,1,m) scanf("%d%d",&x,&y),G[x].pb(y);
    rep(i,1,n) if(!vis[i]) {
        vis[i] = 1;
        for(auto v: G[i]) if(!vis[v]) vis[v] = -1;
    }
    per(i,n,1) if(vis[i]==1) {
        ++cc;
        for(auto v: G[i]) vis[v]=-1;
    }
    printf("%d\n",cc);
    rep(i,1,n)if(vis[i]==1)printf("%d ",i);puts("");
}

转载于:https://www.cnblogs.com/RRRR-wys/p/9471864.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值