【图论】Codeforces 1019C Sergey's problem

题意:

给出一个有向图,在这个图中选择一些点,这些点不能有边直接相连,并且每个点都能从某个选中的点不超过两步到达。

求任意一个方案。


分析:

也是非常简单的一道题。

任意找一个没被删除的点,删去它及它连向的点,对剩下的图继续做,直到删空为止。

然后按照删的反向顺序依次考虑:若所有连向它的点都没被选中,则选中这个点不会造成矛盾,直接选。否则就不选。这两种情况中,都能保证该点以及它的所有后继节点都是合法的。因为如果它的前驱节点没被选,就选中这个点,它的后继就能从这里出发,走一步到达。如果它前驱节点某一个被选了,那就能通过该点,走两步到达它的后继节点。

而且用的是反向的顺序,所以每次考虑一个点选不选的时候,它的所有前驱也一定是合法的。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 1000010
using namespace std;
bool used[MAXN],del[MAXN];
vector<int> a[MAXN],b[MAXN];
int n,m;
void dfs(int x){
    for(int i=x;i<=n;i++)
        if(del[i]==0){
            del[i]=1;
            for(int j=0;j<a[i].size();j++)
                del[a[i][j]]=1;
            dfs(i+1);
            used[i]=1;
            for(int j=0;j<b[i].size();j++)
                if(used[b[i][j]]==1){
                    used[i]=0;
                    break;
                }
            return ;
        }
}
int main(){
    SF("%d%d",&n,&m);
    int u,v;
    for(int i=1;i<=m;i++){
        SF("%d%d",&u,&v);
        a[u].push_back(v);
        b[v].push_back(u);
    }
    dfs(1);
    int cnt=0;
    for(int i=1;i<=n;i++)
        if(used[i]==1)
            cnt++;
    PF("%d\n",cnt);
    for(int i=1;i<=n;i++)
        if(used[i]==1)
            PF("%d ",i);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值