

Hãy luôn nhớ cảm ơn và vote 5*
nếu câu trả lời hữu ích nhé!
Cách giải: u tới được v và v cũng tới được u thì u, v thuộc 1 tplt mạnh (scc).
số cạnh để nối hết các đỉnh trong 1 tplt mạnh là: Gọi n là số đỉnh trong tplt mạnh đó
=> số cạnh n*(n - 1) (quy tắc nhân).
Nhưng trong tplt đó đã có sẵn x cạnh nên đáp án cho tplt đó là n - x.
Như vậy đáp án chính là tổng cách cạnh có thể tạo ra của các tplt mạnh.
Lưu ý: Vì đề cho cạnh trùng nên dẫn tới việc tính sai nên ta cần thêm bước khử cạnh trùng:
Link code: ideone.com/VEMdQD
Code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int long long
const int MAXN = 1e5 + 7;
int low[MAXN], id[MAXN], dfstime, scc[MAXN], cnt, ans, save[MAXN], node[MAXN];
int n, m;
bool mark[MAXN];
vector <int> a[MAXN];
set <int> s[MAXN];
stack <int>st;
void dfs(int u){
low[u] = id[u] = ++dfstime;
st.push(u);
for(auto v : a[u]){
if(!mark[v]){
if(!id[v]){
dfs(v);
low[u] = min(low[v], low[u]);
}
else low[u] = min(low[u], id[v]);
}
}
if(low[u] == id[u]){
int v;
cnt++;
do{
v = st.top();
st.pop();
scc[v] = cnt;
mark[v] = 1;
node[cnt]++;
}while(u != v);
}
}
signed main(){
ios_base::sync_with_stdio(0);
cout.tie(0);
cin.tie(0);
cin >> n >> m;
for(int i = 1; i <= m; i++){
int x, y;
cin >> x >> y;
if(s[x].find(y) == s[x].end()){
a[x].push_back(y);
s[x].insert(y);
}
}
for(int i = 1; i <= n; i++) if(!id[i])dfs(i);
for(int u = 1; u <= n; u++)
for(auto v : a[u])
if(scc[u] == scc[v]) save[scc[v]]++;
for(int i = 1; i <= cnt; i++){
int cur = node[i];
cur = (cur * (cur - 1));
ans += cur - save[i];
}
cout << ans;
}
-----------------------------
**Xin 5* ạ**
Hãy giúp mọi người biết câu trả lời này thế nào?
Bảng tin