zoukankan      html  css  js  c++  java
  • 【Cf #503 C】Sergey's problem(有趣的构造)

    感觉这种构造题好妙啊,可我就是想不到诶。

    给出一张无自环的有向图,回答一个独立集,使得图中任意一点都可以被独立集中的某一点两步之内走到。

     具体构造方案如下:

    1. 下标从小到大枚举点,如果该点没有任何标记,则将其标记为$-1$,即答案的候选点,并把它能一步走到的未访问的点标记为$1$,即不会成为答案的点。
    2. 下标从大到小进行第二次枚举,如果该点被标为$-1$并且没有被丢弃,则选则该点,并把它能一步走到的点丢弃。

    我们来考虑它的正确性:

    显然它是一个独立集。唯一的问题在与它有可能出现两个同为$-1$的点相连(事实上他们组成的是一个$Dag$),这时注意到有出边的那个点的标号一定比较大,我们在计算答案时一定会先选这个点,然后就不会选有入边的那个点了。

    每个点都能被两步内走到。如果它是被标为$-1$的点却不在答案中,那一定存在一个$-1$点能一步到达它,由上述可知。如果它是一个$1$点,那一定有一个$-1$点与它直接相连,两步内就一定能走到了。

    #include <cstdio>
    #include <vector>
    
    const int N = 1000005;
    
    int n, m, vis[N], usd[N];
    std::vector<int> g[N], ans;
    
    int main() {
      scanf("%d%d", &n, &m);
      for (int i = 1, x, y; i <= m; ++i) {
        scanf("%d%d", &x, &y);
        g[x].push_back(y);
      }
      for (int i = 1; i <= n; ++i) {
        if (vis[i] != 0) continue;
        vis[i] = -1;
        for (int v : g[i]) if (vis[v] == 0) vis[v] = 1;
      }
      for (int i = n; i >= 1; --i) {
        if (vis[i] != -1 || usd[i]) continue;
        ans.push_back(i);
        for (int v : g[i]) usd[v] = 1;
      }
      printf("%lu
    ", ans.size());
      for (int v : ans) printf("%d ", v);
      
      return 0;
    }
    View Code
  • 相关阅读:
    webpack学习(一)—— 入门
    AMD 规范
    CommonJS 规范
    webpack 故障处理
    webpack 开发环境
    webpack 插件
    webpack 配置文件
    webpack 使用
    webpack Loader
    webpack常用的插件安装命令
  • 原文地址:https://www.cnblogs.com/Dance-Of-Faith/p/9469889.html
Copyright © 2011-2022 走看看