图论板子合集
树哈希
image-20250905230039500
双线格路计数
image-20250905230124802
dij
void dijkstra() {
memset(dis, 0x3f, sizeof(dis));
dis[s] = 0;
priority_queue<pii, vector
q.push(make_pair(0, s));
while (!q.empty()) {
int x = q.top().second;
q.pop();
if (vis[x])
continue;
vis[x] = 1;
for (int i = head[x]; i; i = e[i].nex) {
int v = e[i].y;
if (dis[v] > dis[x] + e[i].z)
dis[v] = dis[x] + e[i].z, q.push(make_pair(dis[v], v));
}
}
return;
}
差分约束
include <bits/stdc++.h>
using namespace std;
define int long long
define pii pair<int, int>
define mp make_pair
define db double
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
namespace IO {
void openfile() {
ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
endif
}
int add(int x, int y) {
x += y;
return x >= mod ? x - mod : x;
}
int sub(int x, int y) {
x -= y;
return x < 0 ? x + mod : x;
}
int mul(int x, int y) {
return 1ll * x * y % mod;
}
int qpow(int x, int y = mod - 2) {
int ans = 1;
while (y) {
if (y & 1)
ans = 1ll * x * ans % mod;
x = 1ll * x * x % mod;
y >>= 1;
}
return ans;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, m, dis[maxn], in[maxn], vis[maxn];
vector
void spfa() {
memset(dis, 0x3f, sizeof(dis));
queue
dis[0] = 0, q.push(0);
while (!q.empty()) {
int x = q.front();
q.pop();
vis[x] = 0;
in[x]++;
if (in[x] == n) {
puts("NO");
exit(0);
}
for (auto V : e[x]) {
int v = V.first, z = V.second;
if (dis[v] > dis[x] + z) {
dis[v] = dis[x] + z;
if (!vis[v])
q.push(v), vis[v] = 1;
}
}
}
for (int i = 1; i <= n; i++)
printf("%lld ", dis[i]);
puts("");
}
signed main() {
openfile();
n = read(), m = read();
for (int i = 1; i <= m; i++) {
int x = read(), y = read(), z = read();
e[y].push_back(mp(x, z));
}
for (int i = 1; i <= n; i++)
e[0].push_back(mp(i, 0));
spfa();
return 0;
}
最小直径生成树
include
include
include
include
using namespace std;
constexpr int MAXN = 502;
using ll = long long;
using pii = pair<int, int>;
ll d[MAXN][MAXN], dd[MAXN][MAXN], rk[MAXN][MAXN], val[MAXN];
constexpr ll INF = 1e17;
int n, m;
bool cmp(int a, int b) { return val[a] < val[b]; }
void floyd() {
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
struct node {
ll u, v, w;
} a[MAXN * (MAXN - 1) / 2];
void solve() {
// 求图的绝对中心
floyd();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
rk[i][j] = j;
val[j] = d[i][j];
}
sort(rk[i] + 1, rk[i] + 1 + n, cmp);
}
ll P = 0, ansP = INF;
// 在点上
for (int i = 1; i <= n; i++) {
if (d[i][rk[i][n]] * 2 < ansP) {
ansP = d[i][rk[i][n]] * 2;
P = i;
}
}
// 在边上
int f1 = 0, f2 = 0;
ll disu = INT_MIN, disv = INT_MIN, ansL = INF;
for (int i = 1; i <= m; i++) {
ll u = a[i].u, v = a[i].v, w = a[i].w;
for (int p = n, i = n - 1; i >= 1; i--) {
if (d[v][rk[u][i]] > d[v][rk[u][p]]) {
if (d[u][rk[u][i]] + d[v][rk[u][p]] + w < ansL) {
ansL = d[u][rk[u][i]] + d[v][rk[u][p]] + w;
f1 = u, f2 = v;
disu = (d[u][rk[u][i]] + d[v][rk[u][p]] + w) / 2 - d[u][rk[u][i]];
disv = w - disu;
}
p = i;
}
}
}
cout << min(ansP, ansL) / 2 << '\n';
// 最小路径生成树
vector
for (int i = 1; i <= 501; ++i)
for (int j = 1; j <= 501; ++j) dd[i][j] = INF;
for (int i = 1; i <= 501; ++i) dd[i][i] = 0;
if (ansP <= ansL) {
for (int j = 1; j <= n; j++) {
for (int i = 1; i <= m; ++i) {
ll u = a[i].u, v = a[i].v, w = a[i].w;
if (dd[P][u] + w == d[P][v] && dd[P][u] + w < dd[P][v]) {
dd[P][v] = dd[P][u] + w;
pp.push_back({u, v});
}
u = a[i].v, v = a[i].u, w = a[i].w;
if (dd[P][u] + w == d[P][v] && dd[P][u] + w < dd[P][v]) {
dd[P][v] = dd[P][u] + w;
pp.push_back({u, v});
}
}
}
for (auto [x, y] : pp) cout << x << ' ' << y << '\n';
} else {
d[n + 1][f1] = disu;
d[f1][n + 1] = disu;
d[n + 1][f2] = disv;
d[f2][n + 1] = disv;
a[m + 1].u = n + 1, a[m + 1].v = f1, a[m + 1].w = disu;
a[m + 2].u = n + 1, a[m + 2].v = f2, a[m + 2].w = disv;
n += 1;
m += 2;
floyd();
P = n;
for (int j = 1; j <= n; j++) {
for (int i = 1; i <= m; ++i) {
ll u = a[i].u, v = a[i].v, w = a[i].w;
if (dd[P][u] + w == d[P][v] && dd[P][u] + w < dd[P][v]) {
dd[P][v] = dd[P][u] + w;
pp.push_back({u, v});
}
u = a[i].v, v = a[i].u, w = a[i].w;
if (dd[P][u] + w == d[P][v] && dd[P][u] + w < dd[P][v]) {
dd[P][v] = dd[P][u] + w;
pp.push_back({u, v});
}
}
}
cout << f1 << ' ' << f2 << '\n';
for (auto [x, y] : pp)
if (x != n && y != n) cout << x << ' ' << y << '\n';
}
}
void init() {
for (int i = 1; i <= 501; ++i)
for (int j = 1; j <= 501; ++j) d[i][j] = INF;
for (int i = 1; i <= 501; ++i) d[i][i] = 0;
}
int main() {
init();
cin >> n >> m;
for (int i = 1; i <= m; ++i) {
ll u, v, w;
cin >> u >> v >> w;
w *= 2;
d[u][v] = w, d[v][u] = w;
a[i].u = u, a[i].v = v, a[i].w = w;
}
solve();
return 0;
}
斯坦纳树
include <bits/stdc++.h>
using namespace std;
define int long long
define pii pair<int, int>
define mp make_pair
const int maxn = 110;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
namespace IO {
void openfile() {
ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
endif
}
int mul(int x, int y) {
return 1ll * x * y % mod;
}
int add(int x, int y) {
x += y;
if (x >= mod)
x -= mod;
return x;
}
int sub(int x, int y) {
return add(x, mod - y);
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int f[1030][maxn];
int n, m, k, vis[maxn];
vector
void spfa(int s) {
queue
for (int i = 1; i <= n; i++)
if (f[s][i] != 0x3f3f3f3f)
vis[i] = 1, q.push(i);
while (!q.empty()) {
int x = q.front();
q.pop();
vis[x] = 0;
for (auto vv : e[x]) {
int v = vv.first, z = vv.second;
if (f[s][v] > f[s][x] + z) {
f[s][v] = f[s][x] + z;
if (!vis[v])
vis[v] = 1, q.push(v);
}
}
}
}
signed main() {
openfile();
n = read(), m = read(), k = read();
for (int i = 1; i <= m; i++) {
int x = read(), y = read(), z = read();
e[x].push_back(mp(y, z));
e[y].push_back(mp(x, z));
}
memset(f, 0x3f, sizeof(f));
for (int i = 0; i < k; i++) {
int x = read();
f[1 << i][x] = 0;
}
for (int s = 1; s < (1 << k); s++) {
for (int t = s & (s - 1); t; t = (t - 1) & s) {
if (t < (s ^ t))
break;
for (int i = 1; i <= n; i++)
f[s][i] = min(f[s][i], f[t][i] + f[s ^ t][i]);
}
spfa(s);
}
int ans = 0x3f3f3f3f;
for (int i = 1; i <= n; i++)
ans = min(ans, f[(1 << k) - 1][i]);
printf("%lld\n", ans);
cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
return 0;
}
强连通分量
include <bits/stdc++.h>
using namespace std;
define ll long long
define pii pair<int, int>
define mp make_pair
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const ll inf = 0x3f3f3f3f3f3f3f3f;
namespace IO {
void openfile() {
ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
endif
}
int add(ll x, ll y) {
x += y;
return x >= mod ? x - mod : x;
}
int sub(int x, int y) {
x -= y;
return x < 0 ? x + mod : x;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, m;
int bl[maxn], cnt, a[maxn], w[maxn];
int sta[maxn], top, vis[maxn];
int dfn[maxn], low[maxn], tim;
int x[maxn], y[maxn], ans, len[maxn], in[maxn];
vector
void tarjan(int x) {
low[x] = dfn[x] = ++tim;
sta[++top] = x, vis[x] = 1;
for (auto v : e[x]) {
if (!dfn[v])
tarjan(v), low[x] = min(low[x], low[v]);
else if (vis[v])
low[x] = min(low[x], dfn[v]);
}
if (low[x] == dfn[x]) {
int y;
++cnt;
do {
y = sta[top--], vis[y] = 0;//记得清空
bl[y] = cnt;
w[cnt] += a[y];
} while (y != x);
}
}
void topo() {
queue
for (int i = 1; i <= cnt; i++)
if (!in[i])
q.push(i), len[i] = w[i];
while (!q.empty()) {
int x = q.front();
q.pop();
ans = max(ans, len[x]);
for (auto v : e[x]) {
len[v] = max(len[v], len[x] + w[v]);
in[v]--;
if (!in[v])
q.push(v);
}
}
}
signed main() {
openfile();
n = read(), m = read();
for (int i = 1; i <= n; i++)
a[i] = read();
for (int i = 1; i <= m; i++) {
x[i] = read(), y[i] = read();
e[x[i]].push_back(y[i]);
}
for (int i = 1; i <= n; i++)
if (!dfn[i])
tarjan(i);
for (int i = 1; i <= n; i++)
e[i].clear();
for (int i = 1; i <= m; i++) {
if (bl[x[i]] == bl[y[i]])
continue;
e[bl[x[i]]].push_back(bl[y[i]]);
in[bl[y[i]]]++;
}
topo();
printf("%d\n", ans);
cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
return 0;
}
边双
include <bits/stdc++.h>
using namespace std;
define ll long long
define pii pair<int, int>
define mp make_pair
const int maxn = 4e6 + 10;
const int mod = 1e9 + 7;
const ll inf = 0x3f3f3f3f3f3f3f3f;
namespace IO {
void openfile() {
ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
endif
}
int mul(int x, int y) {
return 1ll * x * y % mod;
}
int add(ll x, ll y) {
x += y;
if (x >= mod)
x -= mod;
return x;
}
int sub(int x, int y) {
return add(x, mod - y);
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, m;
int head[maxn], tot = 1, tim;
int bri[maxn << 1], dfn[maxn], low[maxn], vis[maxn], cnt;
vector
struct node {
int y, nex;
} e[maxn << 1];
void add(int x, int y) {
e[++tot] = {y, head[x]};
head[x] = tot;
}
void tarjan(int x, int b) {
low[x] = dfn[x] = ++tim;
for (int i = head[x]; i; i = e[i].nex) {
int v = e[i].y;
if (!dfn[v]) {
tarjan(v, i);
low[x] = min(low[x], low[v]);
if (low[v] > dfn[x])
bri[i] = bri[i ^ 1] = 1;
}
else if (i != (b ^ 1))
low[x] = min(low[x], dfn[v]);
}
}
void dfs2(int x) {
if (vis[x])
return;
vis[x] = 1;
ans[cnt].push_back(x);
for (int i = head[x]; i; i = e[i].nex) {
int v = e[i].y;
if (bri[i] || vis[v])
continue;
dfs2(v);
}
}
signed main() {
openfile();
n = read(), m = read();
for (int i = 1; i <= m; i++) {
int x = read(), y = read();
if (x == y)
continue;
add(x, y), add(y, x);
}
for (int i = 1; i <= n; i++)
if (!dfn[i])
tarjan(i, 0);
for (int i = 1; i <= n; i++)
if (!vis[i])
++cnt, dfs2(i);
cout << cnt << endl;
for (int i = 1; i <= cnt; i++) {
printf("%d ", ans[i].size());
for (auto v : ans[i])
printf("%d ", v);
puts("");
}
cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
return 0;
}
点双(铁人两项)
include <bits/stdc++.h>
using namespace std;
define int long long
define pii pair<int, int>
define mp make_pair
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
namespace IO {
void openfile() {
ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
endif
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, m;
int ans;
int fa[maxn], dfn[maxn], tim, low[maxn], sta[maxn], top, cnt;
int num, siz[maxn], a[maxn];
vector
void add(int x, int y) {
g[x].push_back(y), g[y].push_back(x);
}
void tarjan(int x) {
dfn[x] = low[x] = ++tim;
++num;
sta[++top] = x;
for (auto v : e[x]) {
if (!dfn[v]) {
tarjan(v), low[x] = min(low[x], low[v]);
if (dfn[x] == low[v]) {
++cnt;
while (sta[top + 1] != v)
add(sta[top], cnt), top--, a[cnt]++;
add(x, cnt);
a[cnt]++;
}
}
else
low[x] = min(low[x], dfn[v]);
}
}
void dfs(int x, int fa) {
siz[x] = (x <= n);
for (auto v : g[x]) {
if (v == fa)
continue;
dfs(v, x);
ans += 2 * siz[x] * siz[v] * a[x];
siz[x] += siz[v];
}
ans += 2 * siz[x] * (num - siz[x]) * a[x];
}
signed main() {
openfile();
n = read(), m = read();
cnt = n;
for (int i = 1; i <= m; i++) {
int x = read(), y = read();
e[x].push_back(y), e[y].push_back(x);
}
for (int i = 1; i <= n; i++)
a[i] = -1;
for (int i = 1; i <= n; i++)
if (!dfn[i])
num = 0, tarjan(i), top--, dfs(i, 0);
printf("%lld\n", ans);
cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
return 0;
}
欧拉路
image-20250905230918376
include <bits/stdc++.h>
using namespace std;
const int MAX=100010;
int n,m,u,v,del[MAX];
int du[MAX][2];//记录入度和出度
stack
vector
void dfs(int now)
{
for(int i=del[now];i<G[now].size();i=del[now])
{
del[now]=i+1;
dfs(G[now][i]);
}
st.push(now);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d",&u,&v),G[u].push_back(v),du[u][1]++,du[v][0]++;
for(int i=1;i<=n;i++) sort(G[i].begin(),G[i].end());
int S=1,cnt[2]={0,0}; //记录
bool flag=1; //flag=1表示,所有的节点的入度都等于出度,
for(int i=1;i<=n;i++)
{
if(du[i][1]!=du[i][0])
{
flag=0;
if(du[i][1]-du[i][0]1/出度比入度多1/) cnt[1]++,S=i;
else if(du[i][0]-du[i][1]1/入度比出度多1/) cnt[0]++;
else return puts("No"),0;
}
}
if((!flag)&&!(cnt[0]cnt[1]&&cnt[0]1)) return !puts("No"),0;
//不满足欧拉回路的判定条件,也不满足欧拉路径的判定条件,直接输出"No"
dfs(S);
while(!st.empty()) printf("%d ",st.top()),st.pop();
return 0;
}
最大流
include <bits/stdc++.h>
using namespace std;
define int long long
const int maxn = 1010;
int d[maxn];
int n, m, s, t;
struct node {
int y, z, nex;
} e[10010 * 2];
int head[maxn], tot = 1, hd[maxn];
void add(int x, int y, int z) {
e[++tot] = {y, z, head[x]};
head[x] = tot;
}
int ans;
bool bfs() {
memset(d, 0, sizeof(d));
queue
q.push(s), d[s] = 1;
while (!q.empty()) {
int x = q.front();
q.pop();
for (int i = head[x]; i; i = e[i].nex) {
int v = e[i].y;
if (e[i].z && !d[v])
d[v] = d[x] + 1, q.push(v);
}
}
return d[t];
}
int dfs(int x, int in) {
if (x == t || !in)
return in;
int out = 0;
for (int& i = hd[x]; i; i = e[i].nex) {
int v = e[i].y;
if (e[i].z && d[v] == d[x] + 1) {
int res = dfs(v, min(e[i].z, in));
e[i].z -= res, e[i ^ 1].z += res;
in -= res, out += res;
if (!in)
break;
}
}
return out;
}
signed main() {
ios::sync_with_stdio(false);
cin >> n >> m >> s >> t;
for (int i = 1; i <= m; i++) {
int x, y, z;
cin >> x >> y >> z;
add(x, y, z);
add(y, x, 0);
}
while (bfs()) {
memcpy(hd, head, sizeof(head));
ans += dfs(s, 1e18);
}
cout << ans << endl;
return 0;
}
费用流
include <bits/stdc++.h>
using namespace std;
define int long long
const int maxn = 5010;
int n, m, s, t;
int d[maxn], vis[maxn];
int head[maxn], tot = 1, ans, cost;
struct node {
int y, z, w, nex;
} e[maxn * 20];
void add(int x, int y, int z, int w) {
e[++tot] = {y, z, w, head[x]};
head[x] = tot;
}
bool spfa() {
queue
memset(d, 0x3f, sizeof(d));
memset(vis, 0, sizeof(vis));
d[s] = 0;
q.push(s);
while (!q.empty()) {
int x = q.front();
q.pop();
vis[x] = 0;
for (int i = head[x]; i; i = e[i].nex) {
int v = e[i].y;
if (e[i].z && d[v] > d[x] + e[i].w) {
d[v] = d[x] + e[i].w;
if (!vis[v])
q.push(v), vis[v] = 1;
}
}
}
return d[t] != 0x3f3f3f3f3f3f3f3f;
}
int dfs(int x, int in) {
if (!in || x == t)
return in;
int out = 0;
vis[x] = 1;
for (int i = head[x]; i && in; i = e[i].nex) {
int v = e[i].y;
if (!e[i].z || d[v] != d[x] + e[i].w || vis[v])
continue;
int res = dfs(v, min(in, e[i].z));
out += res, in -= res;
e[i].z -= res, e[i ^ 1].z += res;
}
if (!out)
d[x] = 0x3f3f3f3f3f3f3f3f;
return out;
}
void dinic() {
while (spfa()) {
int k = dfs(s, 1e18);
ans += k;
cost += k * d[t];
}
cout << ans << ' ' << cost << endl;
return;
}
signed main() {
ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
endif
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m >> s >> t;
for (int i = 1; i <= m; i++) {
int x, y, z, w;
cin >> x >> y >> z >> w;
add(x, y, z, w), add(y, x, 0, -w);
}
dinic();
return 0;
}
有源汇上下界最小流
include <bits/stdc++.h>
using namespace std;
define int long long
const int maxn = 50008;
const int maxm = 125008;
const int inf = 1e18 + 7;
int n, m;
int head[maxn], tot = 1, hd[maxn];
int down, d[maxn], s, t, ss, tt, sum;
int du[maxn];
inline void read(int& x) {
x = 0;
char c = getchar();
while (!isdigit(c))
c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
}
struct node {
int y, z, nex;
} e[((maxm + maxn + 5) << 1) | 5];
void add(int x, int y, int z) {
e[++tot] = {y, z, head[x]};
head[x] = tot;
}
inline bool bfs() {
memset(d, 0, sizeof(d));
queue
q.push(s);
d[s] = 1;
while (!q.empty()) {
int x = q.front();
q.pop();
for (int i = head[x]; i; i = e[i].nex) {
int v = e[i].y;
if (e[i].z && !d[v]) {
d[v] = d[x] + 1;
q.push(v);
}
}
}
return d[t];
}
int dfs(int x, int in) {
if (x == t || !in)
return in;
int out = 0;
for (int& i = hd[x]; i; i = e[i].nex) {
int v = e[i].y;
if (e[i].z && d[v] == d[x] + 1) {
int res = dfs(v, min(e[i].z, in));
e[i].z -= res, e[i ^ 1].z += res;
in -= res, out += res;
if (!in)
break;
}
}
if (!out)
d[x] = -1;
return out;
}
int dinic() {
int ans = 0;
while (bfs()) {
memcpy(hd, head, sizeof hd);
ans += dfs(s, inf);
}
return ans;
}
signed main() {
ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
endif
read(n), read(m), read(ss), read(tt);
for (int i = 1; i <= m; i++) {
int x, y, up;
read(x), read(y), read(down), read(up);
add(x, y, up - down);
add(y, x, 0);
du[x] -= down, du[y] += down;
}
s = n + 1, t = n + 2;
for (int i = 1; i <= n; i++) {
if (!du[i])
continue;
if (du[i] > 0) {
add(s, i, du[i]), add(i, s, 0);
sum += du[i];
}
else
add(i, t, -du[i]), add(t, i, 0);
}
add(tt, ss, inf), add(ss, tt, 0);
int res = dinic();
if (res != sum)
cout << "please go home to sleep" << endl;
if (res == sum) {
int x = e[tot].z;
e[tot].z = e[tot - 1].z = 0;
s = ss, t = tt;
swap(s, t);
int ans = dinic();
cout << x - ans << endl;
}
return 0;
}
无源汇上下界可行流
include <bits/stdc++.h>
using namespace std;
define int long long
const int maxn = 100010;
int n, m;
int head[maxn], tot = 1;
int du[maxn], sum, s, t;
int d[maxn], down[maxn];
struct node {
int y, z, nex;
} e[maxn];
void add(int x, int y, int z) {
e[++tot] = {y, z, head[x]};
head[x] = tot;
}
bool bfs() {
queue
memset(d, 0, sizeof(d));
q.push(s);
d[s] = 1;
while (!q.empty()) {
int x = q.front();
q.pop();
for (int i = head[x]; i; i = e[i].nex) {
int y = e[i].y;
if (!d[y] && e[i].z) {
d[y] = d[x] + 1;
q.push(y);
}
}
}
return d[t];
}
int dfs(int x, int in) {
if (x == t || !in)
return in;
int out = 0;
for (int i = head[x]; in && i; i = e[i].nex) {
int v = e[i].y;
if (d[v] == d[x] + 1 && e[i].z) {
int res = dfs(v, min(e[i].z, in));
out += res;
in -= res;
e[i].z -= res;
e[i ^ 1].z += res;
}
}
if (!out)
d[x] = 0;
return out;
}
int dinic() {
int ans = 0;
while (bfs())
ans += dfs(s, 1e18);
return ans;
}
signed main() {
ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
endif
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int x, y, up;
cin >> x >> y >> down[i] >> up;
add(x, y, up - down[i]);
add(y, x, 0);
du[y] += down[i], du[x] -= down[i];
}
s = n + 1, t = n + 2;
for (int i = 1; i <= n; i++) {
if (!du[i])
continue;
if (du[i] > 0)
add(s, i, du[i]), add(i, s, 0), sum += du[i];
else
add(i, t, -du[i]), add(t, i, 0);
}
int res = dinic();
if (res == sum) {
cout << "YES" << endl;
for (int i = 1; i <= m; i++)
cout << down[i] + e[i * 2 + 1].z << endl;
} else
cout << "NO" << endl;
return 0;
}
image-20250905231424609
prufer 序列
include <bits/stdc++.h>
using namespace std;
define int long long
define pii pair<int, int>
define mp make_pair
define db double
const int maxn = 5e6 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
namespace IO {
void openfile() {
ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
endif
}
void Min(int& x, int y) {
x = (x < y) ? x : y;
}
void Max(int& x, int y) {
x = (x > y) ? x : y;
}
int add(int x, int y) {
return (x + y) >= mod ? (x + y - mod) : (x + y);
}
int sub(int x, int y) {
return (x < y) ? (x + mod - y) : (x - y);
}
void Add(int& x, int y) {
x = (x + y) >= mod ? (x + y - mod) : (x + y);
}
void Sub(int& x, int y) {
x = (x < y) ? (x - y + mod) : (x - y);
}
int mul(int x, int y) {
return 1ll * x * y % mod;
}
void Mul(int& x, int y) {
x = 1ll * x * y % mod;
}
int qpow(int x, int y = mod - 2) {
int ans = 1;
while (y) {
if (y & 1)
ans = 1ll * x * ans % mod;
x = 1ll * x * x % mod, y >>= 1;
}
return ans;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, m;
int fa[maxn], a[maxn], in[maxn], vis[maxn];
vector
void solve1() {
for (int i = 1; i < n; i++)
fa[i] = read(), in[fa[i]]++;
int cnt = 0;
for (int i = 1; i < n; i++)
if (!in[i] && cnt < n - 2) {
a[++cnt] = fa[i];
in[fa[i]]--;
int now = fa[i];
while (cnt < n - 2 && in[now] == 0 && now < i && now != n)
a[++cnt] = fa[now], in[fa[now]]--, now = fa[now];
}
int ans = 0;
for (int i = 1; i <= n; i++)
ans ^= i * a[i];
cout << ans;
}
void solve2() {
for (int i = 1; i < n - 1; i++)
a[i] = read(), in[a[i]]++;
a[n - 1] = n;
int cnt = 0;
for (int i = 1; i < n; i++) {
if (!in[i]) {
fa[i] = a[++cnt];
in[fa[i]]--;
int now = fa[i];
while (cnt < n - 1 && in[now] == 0 && now < i && now != n)
fa[now] = a[++cnt], in[fa[now]]--, now = fa[now];
}
}
int ans = 0;
for (int i = 1; i <= n; i++)
ans ^= i * fa[i];
cout << ans;
}
signed main() {
openfile();
n = read(), m = read();
if (m == 1)
solve1();
else
solve2();
return 0;
}
矩阵树
image-20250905232011044
image-20250905232116072
LGV
include <bits/stdc++.h>
using namespace std;
define ll long long
define pii pair<int, int>
define mp make_pair
define db double
const int maxn = 2e6 + 10;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
namespace IO {
void openfile() {
ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
endif
}
void Min(int& x, int y) {
x = (x < y) ? x : y;
}
void Max(int& x, int y) {
x = (x > y) ? x : y;
}
int add(int x, int y) {
return (x + y) >= mod ? (x + y - mod) : (x + y);
}
int sub(int x, int y) {
return (x < y) ? (x + mod - y) : (x - y);
}
void Add(int& x, int y) {
x = (x + y) >= mod ? (x + y - mod) : (x + y);
}
void Sub(int& x, int y) {
x = (x < y) ? (x - y + mod) : (x - y);
}
int mul(int x, int y) {
return 1ll * x * y % mod;
}
void Mul(int& x, int y) {
x = 1ll * x * y % mod;
}
int qpow(int x, int y = mod - 2) {
int ans = 1;
while (y) {
if (y & 1)
ans = 1ll * x * ans % mod;
x = 1ll * x * x % mod, y >>= 1;
}
return ans;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, m, fac[maxn], inv[maxn], ifac[maxn];
int a[maxn], b[maxn], g[1010][1010];
int C(int n, int m) {
if (n < m || m < 0)
return 0;
return 1ll * fac[n] * ifac[m] % mod * ifac[n - m] % mod;
}
void gauss() {
int ans = 1;
for (int i = 1; i <= m; i++) {
for (int j = i; j <= m; j++)
if (g[j][i]) {
if (i ^ j)
swap(g[i], g[j]);
break;
}
for (int j = i + 1; j <= m; j++) {
int inv = 1ll * g[j][i] * qpow(g[i][i]) % mod;
for (int k = i; k <= m; k++)
Sub(g[j][k], 1ll * inv * g[i][k] % mod);
}
ans = 1ll * ans * g[i][i] % mod;
}
printf("%d\n", ans);
}
void solve() {
n = read(), m = read();
for (int i = 1; i <= m; i++)
a[i] = read(), b[i] = read();
for (int i = 1; i <= m; i++)
for (int j = 1; j <= m; j++)
g[i][j] = C(b[j] - a[i] + n - 1, n - 1);
gauss();
}
signed main() {
openfile();
int T = read();
fac[0] = ifac[0] = inv[1] = fac[1] = ifac[1] = 1;
for (int i = 2; i < maxn; i++) {
fac[i] = 1ll * fac[i - 1] * i % mod;
inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
ifac[i] = 1ll * ifac[i - 1] * inv[i] % mod;
}
while (T--)
solve();
return 0;
}