zoukankan      html  css  js  c++  java
  • CF1062F Upgrading Cities

    题目链接

    题意可以转化为:求能到达的点数 + 到达它的点数 (le n - 2) 的点数。

    发现两个问题类似,正反都做一遍即可。现在我们的任务是求它能到达的点数。

    因为 DAG, 考虑拓扑排序。发现如果可能有贡献的话,这个点被取出以后的那个瞬间,队列要么为空,要么只有一个点。如果为空,他肯定能到达剩下的所有点;如果只有一个点,那么我们还要求剩下的(没有入过队的)点都是当前点能到达的。经过仔细思考,我们发现不合法当且仅当队列里剩下的那个点 (y) 有它自己的一个“块”,而 (y) 有自己的“块”就一定有一条出边,对应的那个点只有这一个入度。(这是充要条件,否则会出环)因此特判即可。

    inline void che(int x, int y) {
      for (register int i = head[y]; i; i = e[i].nxt) {
        int to = e[i].to; if (ind[to] == 1) return vis[x] = true, void();
      }
      cnt[x] += n - nwtot;
    }
    inline void topo() {
      front = rear = 0;
      nwtot = 0;
      for (register int i = 1; i <= n; ++i) if (!ind[i])  que[++rear] = i, ++nwtot;
      while (front < rear) {
        int cur = que[++front];
        if (front == rear)  cnt[cur] += n - nwtot;
        else if (rear - front == 1) che(cur, que[front + 1]);
        for (register int i = head[cur]; i; i = e[i].nxt) {
          int to = e[i].to; --ind[to];
          if (!ind[to]) que[++rear] = to, ++nwtot;
        }
      }
    }
    
    int main() {
      read(n); read(m);
      for (register int i = 1; i <= m; ++i) {
        int u, v; read(u), read(v);
        U[i] = u, V[i] = v;
        addedge(u, v);
      }
      topo();
      memset(head, 0, sizeof(head));
      ecnt = 0;
      memset(ind, 0, sizeof(ind));
      for (register int i = 1; i <= m; ++i) addedge(V[i], U[i]);
      topo();
      int ans = 0;
      for (register int i = 1; i <= n; ++i) if (!vis[i] && cnt[i] >= n - 2) ++ans;
      printf("%d
    ", ans);
      return 0;
    }
    
  • 相关阅读:
    如何学习linux编程
    SharpMap学习9调侃WebGIS
    蛮力法01
    SharpMap学习10比例尺
    蛮力法03
    系统学习Linux11点建议
    蛮力算法02
    大地坐标系
    Windows 7下删除右键新建菜单项的多余选项
    GIS中的坐标系相关概念
  • 原文地址:https://www.cnblogs.com/JiaZP/p/13579980.html
Copyright © 2011-2022 走看看