题面
题解
正难则反, 求多少条边不能建
首先完全连通图总边数 n * (n - 1)
减去给出的 m 条边
缩点之后, scc可以互连, 添加边, 使得最后留下一个 出度为1为, 入度为1 的连个 scc就可
即留下一个入度为1的scc, 其他scc建边完全联通, or 留下一个scc出度为1, 其他scc建边完全联通
int n, m, _, k;
vector<VI> h;
int c[N], scnt, st[N], top;
int dfn[N], df, low[N];
bool inst[N];
void tarjan(int x) {
dfn[x] = low[x] = ++df, inst[st[++top] = x] = 1;
for (auto &y : h[x]) {
if (!dfn[y]) { tarjan(y); umin(low[x], low[y]); }
else if (inst[y]) umin(low[x], dfn[y]);
}
if (low[x] == dfn[x]) {
++scnt; int y;
do { inst[y = st[top--]] = 0; c[y] = scnt; } while (x != y);
}
}
int main() {
IOS; int cas = 0;
for (cin >> _; _; --_) {
cin >> n >> m; vector<VI>(n + 1).swap(h);
cout << "Case " << ++cas << ": ";
rep (i, 1, m) {
int u, v; cin >> u >> v;
h[u].pb(v);
}
memset(dfn, 0, sizeof dfn); df = scnt = 0;
rep (i, 1, n) if (!dfn[i]) tarjan(i);
if (scnt == 1) { cout << "-1
"; continue; }
VI cnt(scnt + 1); vector<bool> in(scnt + 1), out(scnt + 1);
rep (i, 1, n) ++cnt[c[i]];
rep (i, 1, n) for (auto &y : h[i]) if (c[i] != c[y]) in[c[y]] = out[c[i]] = 1;
int ans = 1e9;
rep (i, 1, scnt) if (!in[i] || !out[i]) umin(ans, cnt[i]);
cout << (ll)n * (n - 1) - m - (ll)ans * (n - ans) << '
';
}
return 0;
}