1 条题解
-
0
-
走访的总代价是
图的极大联通分量数 - 1
。 -
新建一条边,减少极大联通分量数的方法如下:
- 选择两个属于不同联通分量的点 ,
- 连接 ,这样,联通分量就减少一个。
-
设各极大联通分量的点数为 ,则答案是:
-
这表示
- 选择两个联通分量 ,点数分别为 。
- 任选两个点并联通它们。
- 方案数为 。
关于计算
的值,这是一道蓝桥杯的往年真题。采用暴力算法是 的,且 可以到达 的量级。
因此需要优化为 ,给出两种策略:
-
方案 :维护前缀和 ,并求解 。
-
方案 :注意到
$$(a_1+a_2+\cdots+a_k)^2=a_1^2+a_2^2+\cdots+a_k^2+2\times \sum_{1\le i<j\le k}a_ia_j $$据此可 地取得答案。
求解各联通分量的点数可以采用搜索的方法,时间复杂度是 。
#include <iostream> #include <vector> #include <functional> using namespace std; void solve() { int n, m; cin >> n >> m; vector<vector<int>> adj(n + 1); for (int i = 0; i < m; i++) { int x, y; cin >> x >> y; adj[x].push_back(y); adj[y].push_back(x); } vector<int> sizes; vector<bool> vis(n + 1, false); function<void(int, int&)> dfs = [&](int node, int& size) { size++; for (int neighbor : adj[node]) { if (!vis[neighbor]) { vis[neighbor] = true; dfs(neighbor, size); } } }; for (int i = 1; i <= n; i++) { if (!vis[i]) { vis[i] = true; int size = 0; dfs(i, size); sizes.push_back(size); } } auto smart_calculation = [](const vector<int>& v) { long long sum = 0, sqr_sum = 0; for (int i : v) { sum += i; sqr_sum += (long long)i * i; } return (sum * sum - sqr_sum) / 2; }; cout << smart_calculation(sizes) << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; }
-
- 1
信息
- ID
- 288
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- (无)
- 递交数
- 33
- 已通过
- 8
- 上传者