传送门:https://www.hackerrank.com/contests/world-codesprint-11/challenges/hackerland
【题解】
因为加点每次加1个点1条边,所以不会存在一定要经过后加的那些点才能到达的情况。
直接把最后的图建出来,tarjan缩强联通分量+拓扑排序处理连通性。
拿个bitset维护拓扑排序过程即可。复杂度O(n^2/32)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# include <queue> # include <bitset> # include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 5e5 + 10; const int mod = 1e9+7; # define RG register # define ST static int n, m, head[M], nxt[M], to[M], tot=0, c; struct Graph { int head[M], nxt[M], to[M], tot; inline void set() {tot = 0;} inline void add(int u, int v) { ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; } }G1, G; struct pa { int op, a, b; }q[M]; int DFN = 0, dfn[M], low[M], bel[M], scc = 0; int st[M], stn=0; bool ins[M]; inline void tarjan(int x) { dfn[x] = low[x] = ++DFN; st[++stn] = x; ins[x] = 1; for (int i=G1.head[x]; i; i=G1.nxt[i]) { if(!dfn[G1.to[i]]) { tarjan(G1.to[i]); low[x] = min(low[x], low[G1.to[i]]); } else if(ins[G1.to[i]]) low[x] = min(low[x], dfn[G1.to[i]]); } if(low[x] == dfn[x]) { int t = 0; ++scc; while(t != x) { t = st[stn]; --stn; ins[t] = 0; bel[t] = scc; } } } bitset<50001> bs[50001]; int out[M], ans[M], an=0; queue<int> qu; int main() { G1.set(), G.set(); cin >> n >> m; c = n; for (int i=1, u, v; i<=m; ++i) { scanf("%d%d", &u, &v); G1.add(u, v); } cin >> m; for (int i=1; i<=m; ++i) { scanf("%d%d%d", &q[i].op, &q[i].a, &q[i].b); if(q[i].op==1) { ++c; if(q[i].b) G1.add(c, q[i].a); else G1.add(q[i].a, c); } } for (int i=1; i<=c; ++i) if(!dfn[i]) tarjan(i); // for (int i=1; i<=c; ++i) printf("%d ", bel[i]); for (int i=1; i<=c; ++i) { bs[bel[i]][bel[i]] = 1; for (int j=G1.head[i]; j; j=G1.nxt[j]) if(bel[i] != bel[G1.to[j]]) { bs[bel[i]][bel[G1.to[j]]] = 1; // printf("%d %d ", bel[i], bel[G1.to[j]]); out[bel[i]] ++; G.add(bel[G1.to[j]], bel[i]); } } for (int i=1; i<=scc; ++i) if(!out[i]) qu.push(i); while(!qu.empty()) { int top = qu.front(); qu.pop(); for (int i=G.head[top]; i; i=G.nxt[i]) { --out[G.to[i]]; bs[G.to[i]] |= bs[top]; if(out[G.to[i]] == 0) qu.push(G.to[i]); } } // for (int i=1; i<=n; ++i, cout << endl) // for (int j=1; j<=n; ++j) cout << bs[i][j] << ' '; for (int i=m; i; --i) if(q[i].op == 2) ans[++an] = bs[bel[q[i].a]][bel[q[i].b]]; for (int i=an; i; --i) puts(ans[i] ? "Yes" : "No"); return 0; }