思路大概是这样:首先保证是最多两个极大子图,那么其中一个就会是最大团,在补图上面找最大独立集来确定两个完全图;然后我这么想,对于补图上一条边 u→v,如果 u 和 v 不在同一个完全图里面且加上这条边使得其中一个点与它不在的那个完全图里面的所有点都有连边,那么最大团的 size 就会变大,这条边就符合条件,我觉得这正确性没啥问题,但是只有 10pts,求大佬看看/kk
#include <bits/stdc++.h>
#define ll long long
#define pii pair<int, int>
using namespace std;
const int N = 1e4 + 5, M = 150005;
int n, m, match[N], vis[N], prt[N], deg[N], sz[2], lf[N];
vector <int> G[N];
vector <pii> ans;
pii edg[M];
bool hungary(int u, int col) {
for (int v : G[u]) {
if(vis[v] == col) continue;
vis[v] = col;
if(!match[v] || hungary(match[v], col)) return match[v] = u, 1;
}
return 0;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; ++i) {
int x, y; scanf("%d%d", &x, &y);
edg[i].first = x, edg[i].second = y;
if(lf[x] == 1 || lf[y] == 2 || (lf[x] == 0 && lf[y] == 0)) G[x].emplace_back(y), lf[x] = 1, lf[y] = 2;
else G[y].emplace_back(x), lf[x] = 2, lf[y] = 1;
//G[x].emplace_back(y);// G[y].emplace_back(x);
}
for (int i = 1; i <= n; ++i) hungary(i, i);
for (int i = 1; i <= n; ++i) {
//cout << match[i] << "\n";
if(match[i] != 0) prt[i] = 1, sz[1]++;
}
sz[0] = n - sz[1];
for (int i = 1; i <= n; ++i) deg[i] = sz[prt[i] ^ 1];
for (int k = 1; k <= m; ++k) {
int i = edg[k].first, j = edg[k].second;
if(prt[i] != prt[j]) deg[i]--, deg[j]--;
}
int siz = 0;
for (int k = 1; k <= m; ++k) {
int i = edg[k].first, j = edg[k].second;
if(deg[i] == sz[prt[i] ^ 1] - 1 || deg[j] == sz[prt[j] ^ 1] - 1) ans.emplace_back(min(i, j), max(i, j)), siz++;
}
sort(ans.begin(), ans.end());
printf("%d\n", siz);
for (int i = 0; i < siz; ++i) printf("%d %d\n", ans[i].first, ans[i].second);
return 0;
}