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

BriMon
我曾经落败,如今依然搬运于
2025-08-24 21:43:38,当前版本为作者最后更新于2018-05-12 17:34:16,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
第一个题解诶!
想要食用效果更佳戳这里
其实就是暴力;
可能是因为看不懂题才没做;
一看样例就不想做系列;并没有好好看样例;
大致看了一下分的岛屿

大概是这个样子的,然后每个点之间都有一些连线表示之间是通路,每条路都有一个权值;
其实仔细想想,既然在每个岛屿中行走不算进总花费,那么可以进行一波缩点,我是用并查集维护,直接求出每个联通块;
这样,我们就把一堆点,抽象成了一堆互不联通的块;
这时再加边劝,在每一个联通块内,任何 一个点向外的连线都可看做是这个联通块向外连得线, 这样, 我们把每一个联通块向外的边的权值最小记录下来,当做这个联通块向外的边;
所以,我们只要枚举从哪一个联通块开始出发,把这个联通块与其他联通块的边权和加起来取min再乘2就是答案;
代码奉上:
#include <iostream> #include <algorithm> #include <cstdio> #include <cmath> #include <cstring> using namespace std; #define regi register int n; int fa[505]; inline int Find(int x) { return x == fa[x] ? x : fa[x] = Find(fa[x]); } int dis[505][505]; int cnt; int ans = 0x7f7f7f7f; int pos[505]; int main() { cin >> n; for (regi int i = 1 ; i <= n ; i ++) fa[i] = i; memset(dis, 0x7f, sizeof dis); for (regi int i = 1 ; i <= n ; i ++){ int x, y; scanf("%d%d", &x, &y); int fx = Find(x), fy = Find(y); if (fx != fy) fa[fx] = fy; } for (regi int i = 1 ; i <= n ; i ++){ if (fa[i] == i) pos[++cnt] = i; } for (regi int i = 1 ; i <= n ; i ++){ int fi = Find(i); for (regi int j = 1 ; j <= n ; j ++){ int fj = Find(j); int d; scanf("%d", &d); dis[fi][fj] = min(dis[fi][fj], d); } } for (regi int i = 1 ; i <= cnt ; i ++){ int sum = 0; for (regi int j = 1 ; j <= cnt ; j ++){ if (i == j) continue; sum += dis[pos[i]][pos[j]]; } ans = min(ans, sum); } // printf("dis==%d\n", dis[4][10]); cout << ans * 2 << endl; return 0; } zZhBr
- 1
信息
- ID
- 2006
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者