voiddsu(ll root, ll dad, ll keep){ for (auto son: e[root]) { if (son == dad || son == big[root]) continue; dsu(son, root, 0); } if (big[root]) dsu(big[root], root, 1); for (auto son: e[root]) { if (son == dad || son == big[root]) continue; for (ll i = L[son]; i <= R[son]; i++) { ans += cnt[d[dfn[i]]] * (d[dfn[i]] - d[root]); } for (ll i = L[son]; i <= R[son]; i++) { cnt[d[dfn[i]]]++; } } cnt[d[root]]++; if (keep == 0) { for (ll i = L[root]; i <= R[root]; i++) { cnt[d[dfn[i]]]--; } } }
也就是说,到点 x 的简单路径上最大边权的最小值 \(\leq val\) 的所有点 y 均在 Kruskal
重构树上的某一棵子树内,且恰好为该子树的所有叶子节点。
注意重构树新建了节点,初始化范围为 \(n+m\)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
sort(h + 1, h + 1 + m, cmp);//按照边权排序 for (ll i = 1; i <= m; i++) { ll u = s.find(h[i].u), v = s.find(h[i].v);//并查集 if (u != v) { cnt++; s.merge(u, cnt); s.merge(v, cnt); high[cnt] = h[i].len;//点权为边权 e[u].push_back(cnt); e[cnt].push_back(u); e[v].push_back(cnt); e[cnt].push_back(v); } } dfs(cnt, cnt);
vector<PII> e[N]; vector<ll> ans; ll n, m, cur[N], in[N], out[N], vis[N * 2], st = 0, ed = 0;
boolcmp(PII a, PII b){ if (a.first == b.first) return a.second < b.second; return a.first < b.first; }
voiddfs(ll now){ for (ll &i = cur[now]; i < e[now].size(); i++) { if (!vis[e[now][i].second]) { vis[e[now][i].second] = 1; dfs(e[now][i].first); } } ans.push_back(now); }
voidsolve(){ cin >> n >> m; for (ll i = 1, u, v; i <= m; i++) { cin >> u >> v; e[u].push_back({v, i}); in[v]++; out[u]++; } for (ll i = 1; i <= n; i++) { sort(e[i].begin(), e[i].end(), cmp); if (abs(in[i] - out[i]) > 1) { cout << "No" << endl; return; } if (out[i] - in[i] == 1) { if (st) { cout << "No" << endl; return; } st = i; } if (in[i] - out[i] == 1) { if (ed) { cout << "No" << endl; return; } ed = i; } } if (!st) { st = 1; } dfs(st); if (ans.size() != m + 1) { cout << "No" << endl; return; } for (auto i = ans.rbegin(); i != ans.rend(); ++i) { cout << *i << " "; } cout << endl; }
intmain(){ ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); ll T; T = 1; while (T--) { solve(); } return0; }
如果以无向图为例,求是否存在欧拉回路或者欧拉通路。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
voiddfs(ll now){ for (ll &i = cur[now]; i < e[now].size(); i++) { if (!vis[e[now][i].second]) { vis[e[now][i].second] = 1; vis[e[now][i].second ^ 1] = 1; dfs(e[now][i].first); } } ans.push_back(now); }
for (ll i = 1, u, v; i <= m; i++) { cin >> u >> v; e[u].push_back({v, i * 2});//一定要注意 2 3 是一对,4 5 是一对... e[v].push_back({u, i * 2 + 1}); du[u]++; du[v]++; minn = min({minn, u, v}); }
voidsolve(){ ll ans = 0; cin >> dinicn >> m >> s >> t; for (ll i = 1, u, v, w; i <= m; i++) { cin >> u >> v >> w; e[u].push_back((edge){v, w, e[v].size()}); e[v].push_back((edge){u, 0, e[u].size() - 1}); } while (bfs()) { ans += dfs(s, inf); } cout << ans << endl; }
intmain(){ ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); ll T; T = 1; while (T--) { solve(); } return0; }
cout 输出流控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
int n = 141; // 1)分别以十六进制、十进制、八进制先后输出n cout << "1)" << hex << n << " " << dec << n << " " << oct << n << endl; double x = 1234567.89, y = 12.34567; // 2)保留5位有效数字 cout << "2)" << setprecision(5) << x << " " << y << " " << endl; // 3)保留小数点后面5位 cout << "3)" << fixed << setprecision(5) << x << " " << y << endl; // 4)科学计数法输出,且保留小数点后面5位 cout << "4)" << scientific << setprecision(5) << x << " " << y << endl; // 5)非负数显示正号,输出宽度为12字符,宽度不足则用*填补 cout << "5)" << showpos << fixed << setw(12) << setfill('*') << 12.1 << endl; // 6)非负数不显示正号,输出宽度为12字符,宽度不足则右边用填充字符填充 cout << "6)" << noshowpos << setw(12) << left << 12.1 << endl; // 7)输出宽度为12字符,宽度不足则左边用填充字符填充 cout << "7)" << setw(12) << right << 12.1 << endl; // 8)宽度不足时,负号和数值分列左右,中间用填充字符填充 cout << "8)" << setw(12) << internal << -12.1 << endl; cout << "9)" << 12.1 << endl;