cf982F The Meeting Place Cannot Be Changed

http://codeforces.com/contest/982/problem/F

糊了假算法啊.. fst * 2感觉很不好..

标算 也就是乐滋滋的做法 很棒啊

首先两个特判无解

1.原图没有环

2.把原图一个环的点集去掉之后如果还有环

然后把原图中的环扣出来

此时答案的点集是环的点集的子集

考虑一下环上的边产生的贡献

他们都会对使得一段区间\([l, r]\)不能加入到答案内

求出\([l, r]\)的话dp一下就好了

然后我们就打标记把这一段区间删除掉

答案就是没有被删除的点集

复杂度\(O(n + m)\)

#include <bits/stdc++.h>
#define fo(i, n) for(int i = 1; i <= (n); i ++)
#define out(x) cerr << #x << " = " << x << "\n"
#define type(x) __typeof((x).begin())
#define foreach(it, x) for(type(x) it = (x).begin(); it != (x).end(); ++ it)
using namespace std;
#define SZ(x) ((int) (x).size())
#define mem(x, b) memset((x), b, sizeof (x))
typedef long long ll;
#define QAQ cerr << "233\n";
// by piano
template<typename tp> inline void read(tp &x) {
  x = 0;char c = getchar(); bool f = 0;
  for(; c < '0' || c > '9'; f |= (c == '-'), c = getchar());
  for(; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + c - '0', c = getchar());
  if(f) x = -x;
}
template<typename tp> inline void arr(tp *a, int n) {
  for(int i = 1; i <= n; i ++)
    cout << a[i] << " ";
  puts("");
}
const int N = 3e5 + 233;
int dfn[N], low[N], dfs_clock = 0;
int sccno[N], scc_cnt = 0;
int S[N], top = 0;
vector<int> scc[N], g1[N], g2[N], vec1[N], vec2[N];
int cir[N], num = 0, idx[N], vis[N];
int n, m, st, e_cnt = 0;
pair<int, int> e[N << 2];

inline void link(int x, int y) {
  g1[x].push_back(y); g2[y].push_back(x);
}

inline void GG(void) {
  puts("-1"); exit(0);
}

inline void tarjan(int u, int fat, int fff) {
  dfn[u] = low[u] = ++ dfs_clock; S[++ top] = u;
  for(auto v: fff ? g1[u] : vec1[u]) {
    if(!dfn[v]) tarjan(v, u, fff), low[u] = min(low[u], low[v]);
    else if(!sccno[v]) low[u] = min(low[u], dfn[v]);
  }
  if(low[u] == dfn[u]) {
    scc[++ scc_cnt].clear();
    for(;;) {
      int v = S[top --];
      sccno[v] = scc_cnt; scc[scc_cnt].push_back(v);
      if(v == u) break;
    }
  }
}

inline int dfs(int u) {
  if(vis[u]) return u == st;
  cir[++ num] = u; vis[u] = true;
  for(auto &v: g1[u]) if(dfs(v)) return true;
  -- num;
  return false;
}

inline void doit(int fff) {
  mem(dfn, 0); mem(low, 0); mem(sccno, 0);
  dfs_clock = scc_cnt = top = 0;
  int circle_num = 0;
  for(int i = 1; i <= n; i ++) if(!dfn[i]) tarjan(i, 0, fff);
  for(int i = 1; i <= n; i ++)
    if(low[i] == dfn[i] && SZ(scc[sccno[i]]) > 1) {
      circle_num ++; st = i;
    }
  if(circle_num > 1) {
    GG();
  }
}

namespace solver {
  struct NODE {
    int mn, mx;
    NODE(int _mn = 1e9 ,int _mx = 0) {
      mn = _mn; mx = _mx;
    }
    inline void ovo(void) {
      cout << mn << " " << mx << "\n";
    }
  }F1[N], F2[N];
  int cnt[N], vis[N];
  inline void dp(void) {
    auto ban = [&] (int l, int r) -> void {
                if(r > num || l < 1 || l > r) return ;
                ++ cnt[l]; -- cnt[r + 1];
              };
    for(int i = 1; i <= num; i ++) {
      if(F1[cir[i]].mx >= i) ban(i + 1, F1[cir[i]].mx - 1);
      if(F1[cir[i]].mn <= i) ban(i + 1, num);
      if(F2[cir[i]].mx >= i) ban(1, i - 1);
    }
    for(int i = 1; i <= num; i ++) cnt[i] += cnt[i - 1];
    for(int i = 1; i <= num; i ++) if(!cnt[i]) {
      cout << cir[i] << "\n";
      return ;
    }
    GG();
  }
  inline void upd(NODE &a, int mn, int mx) {
    a.mn = min(a.mn, mn);
    a.mx = max(a.mx, mx);
  }
  inline void dfs1(int u) {
    if(vis[u]) return ;
    vis[u] = true;
    for(auto &v: vec1[u]) {
      if(!idx[v]) {
        dfs1(v);
        upd(F1[u], F1[v].mn, F1[v].mx);
      }
      else upd(F1[u], idx[v], idx[v]);
    }
  }
  inline void dfs2(int u) {
    if(vis[u]) return ;
    vis[u] = true;
    for(auto &v: vec2[u]) {
      if(!idx[v]) {
        dfs2(v);
        upd(F2[u], F2[v].mn, F2[v].mx);
      }
      else upd(F2[u], idx[v], idx[v]);
    }
  }
  void main(void) {
    mem(vis, 0);
    for(int i = 1; i <= n; i ++) dfs1(i);
    mem(vis, 0);
    for(int i = 1; i <= n; i ++) dfs2(i);
    dp();
  }
}

main(void) {
  read(n); read(m);
  for(int i = 1; i <= m; i ++) {
    int x, y; read(x); read(y);
    link(x, y);
  }
  doit(1); mem(vis, 0); dfs(st);
  fo(i, num) idx[cir[i]] = i;
  for(int i = 1; i <= n; i ++)
    for(auto &v: g1[i]) {
      if(idx[i] && idx[v] == idx[i] % num + 1) continue;
      else {
        vec1[i].push_back(v);
        vec2[v].push_back(i);
      }
    }
  doit(0);
  solver::main();
}

猜你喜欢

转载自www.cnblogs.com/foreverpiano/p/9067363.html