仙人掌与圆方树(留坑)
先备个份:
check 有向图的仙人掌:
#include <bits/stdc++.h>
#define FASTIO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const int N = 1e4 + 5;
vector<int> g[N];
bool vis[N];
int low[N], dfn[N], dcnt, n, m;
stack<int> st;
int scnt = 0;
bool Tarjan(int u){
dfn[u] = low[u] = ++dcnt;
st.push(u);
vis[u] = true;
int counter = 0;
for(int v : g[u]){
if(!dfn[v]){
bool flag = Tarjan(v);
if (!flag) return false;
low[u] = min(low[u], low[v]);
if (dfn[u] < low[v]) return false;
if (low[v] < dfn[u]) counter ++;
}
else {
if(!vis[v])
return false;
low[u] = min(low[u], dfn[v]);
counter ++;
}
}
// if (counter > 1) {
// cout << "debug : counter limit " << u << " : " << counter << "\n";
// }
if (counter > 1) return false;
// if (mx < low[u]) {
// cout << "debug : too big " << u << '\n';
// }
if(low[u] == dfn[u]){
scnt ++;
while(true){
int v = st.top();
st.pop();
vis[v] = false;
if(u == v) break;
}
}
return true;
}
void solve(void) {
cin >> n >> m;
for (int i = 0; i <= n; ++i)
g[i].clear();
memset(low, 0, sizeof low);
memset(dfn, 0, sizeof dfn);
memset(vis, 0, sizeof vis);
while (st.size()) st.pop();
dcnt = 0;
scnt = 0;
for (int i = 1; i <= m; ++i) {
int u, v; cin >> u >> v;
g[u].push_back(v);
}
for (int i = 0; i < n; ++i)
if (!dfn[i]) {
if (!Tarjan(i)) {
cout << "NO\n";
return;
}
}
if (scnt > 1) {
cout << "NO\n";
return;
}
else {
cout << "YES\n";
}
}
int main() {
FASTIO;
int t; cin >> t;
while (t --)
solve();
return 0;
}
无向图:
#include <bits/stdc++.h>
#define FASTIO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const int N = 1e5 + 5;
vector<int> g[N];
int low[N], dfn[N], cnt[N], dcnt, n, m;
int fa[N];
bool flag = true;
int find(int x) {
if (x == fa[x]) return x;
return fa[x] = find(fa[x]);
}
void dfs(int u, int fa) {
if (!flag) return;
low[u] = dfn[u] = ++dcnt;
for(auto v : g[u]) {
if(!dfn[v]) {
dfs(v, u);
if (!flag) return;
low[u] = min(low[u], low[v]);
if (low[v] < dfn[u])
cnt[u] ++;
}
else if(v != fa) {
low[u] = min(low[u], dfn[v]);
if (dfn[v] < dfn[u])
cnt[u] ++;
}
}
if (cnt[u] > 1) {
flag = false;
}
}
void solve(void) {
cin >> n >> m;
for (int i = 1; i <= n; ++i)
g[i].clear();
for (int i = 1; i <= n; ++i)
fa[i] = i;
memset(cnt, 0, sizeof cnt);
memset(low, 0, sizeof low);
memset(dfn, 0, sizeof dfn);
dcnt = 0;
flag = true;
for (int i = 1; i <= m; ++i) {
int u, v; cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
int fu = find(u), fv = find(v);
if (fu == fv) continue;
fa[fu] = fv;
cout << ":get : " << fu << " " << fv << '\n';
}
int tmp = find(1);
for (int i = 1; i <= n; ++i)
if (find(i) != tmp) {
cout << "NO\n";
return;
}
dfs(1, 0);
if (!flag) {
cout << "NO\n";
}
else {
cout << "YES\n";
}
}
int main() {
FASTIO;
int t; cin >> t;
while (t --) {
solve();
}
return 0;
}