1 条题解
-
0
自动搬运
来自洛谷,原作者为

Ch1F4N
HN 初三最菜 OIer|| 新的赛季 rp ++搬运于
2025-08-24 21:52:07,当前版本为作者最后更新于2023-08-07 20:42:53,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
简要题意是找到一条边连接使得最大团大小增加。
在补图上最大团等于最大独立集。
所以问题转化为删掉一条边使得最大独立集增加,又因为团不超过两个,所以原图是二分图,也就是使得最大匹配减少。
考虑什么样的匹配边是可以被代替的,先跑一遍网络流求最大匹配,不难发现假若一条匹配在残量网络流上的一个环中,那么它就是可以被代替的,所以对残量网络进行缩点,两个端点不在同一个强连通分量中的匹配边可以作为答案。
#include <bits/stdc++.h> using namespace std; const int maxn = 1e4 + 114; const int maxm = 2e6 + 114; const int inf = 0x3f3f3f3f; int maxflow, vis[maxn], tot = 1, cnt; int s, t, n, m, Q, E; vector<int> edge[maxn], Road[maxn]; int hd[maxn], road[maxn], dis[maxn]; map<int, int> f[maxn]; struct edge { int next, to, w; } e[maxm * 2]; void add(int u, int v, int w) { e[++tot].to = v; f[u][v] = tot; e[tot].w = w; e[tot].next = hd[u]; hd[u] = tot; e[++tot].to = u; e[tot].w = 0; e[tot].next = hd[v]; hd[v] = tot; } bool bfs() { memset(dis, 0, sizeof(dis)); dis[s] = 1; queue<int>Q; Q.push(s); while (!Q.empty()) { int u = Q.front(); Q.pop(); road[u] = hd[u]; for (int i = hd[u]; i; i = e[i].next) { int v = e[i].to; if (!dis[v] && e[i].w) { dis[v] = dis[u] + 1; Q.push(v); } } } return dis[t] != 0; } int dinic(int now, int res) { if (now == t) return res; int tp = res; for (int i = road[now]; i; i = e[i].next) { int v = e[i].to; road[now] = i; if (dis[v] == dis[now] + 1 && e[i].w) { int k = min(e[i].w, tp); int del = dinic(v, k); e[i].w -= del; e[i ^ 1].w += del; tp -= del; if (!tp) break; } } return res - tp; } int col[maxn], Use[maxn]; void dfs(int u) { if (Use[u] == 1) return ; Use[u] = 1; for (int v : edge[u]) col[v] = col[u] ^ 1, dfs(v); } int dfsn[maxn]; int low[maxn]; stack<int> S; int Vis[maxn], use[maxn]; int color[maxn], sum = 0; int deep = 0; void paint(int u) { S.pop(); color[u] = sum; Vis[u] = 0; } void tanjan(int u) { dfsn[u] = ++deep; low[u] = deep; Vis[u] = 1; use[u] = 1; S.push(u); for (int i = hd[u]; i; i = e[i].next) { if (e[i].w == 0) continue; int v = e[i].to; if (dfsn[v] == 0) { tanjan(v); low[u] = min(low[u], low[v]); } else { if (Vis[v] != 0) { low[u] = min(low[u], low[v]); } } } if (dfsn[u] == low[u]) { sum++; while (S.top() != u) { paint(S.top()); } paint(u); } return ; } set< pair<int, int>> chifan; int main() { cin >> n >> m; for (int i = 1; i <= m; i++) { int u, v; cin >> u >> v; edge[u].push_back(v); edge[v].push_back(u); } for (int i = 1; i <= n; i++) { if (Use[i] == 0) col[i] = 0, dfs(i); } for (int i = 1; i <= n; i++) { if (col[i] == 0) { for (int nxt : edge[i]) Road[i].push_back(nxt), add(i, nxt, 1); } } s = n + 1, t = n + 2; for (int i = 1; i <= n; i++) if (col[i] == 0) add(s, i, 1); else add(i, t, 1); while (bfs() == true) maxflow += dinic(s, inf); for (int i = 1; i <= n + 2; i++) { if (use[i] == 0) tanjan(i); } for (int i = 1; i <= n; i++) { for (int nxt : Road[i]) { if (e[f[i][nxt]].w == 0 && color[i] != color[nxt]) { chifan.insert(make_pair(min(i, nxt), max(i, nxt))); } } } cout << chifan.size() << '\n'; for (pair<int, int> OUT : chifan) { cout << OUT.first << ' ' << OUT.second << '\n'; } }
- 1
信息
- ID
- 1300
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者