路线规划
nowcoder 217603
题目大意
给一个无向连通图,问你在经过的边最少的前提下,从1走过所有点,再走回1的最短距离
样例#1
输入样例#1
5 5
5 4 3
4 3 5
2 3 7
1 2 4
2 4 1
输出样例#1
26
样例解释#1
最少时间的路径:
1 →2 →4 →3 →4 →5 →4 →2 →1
1 →2 →4 →5 →4 →3 →4 →2 →1
样例#2
输入样例#2
20 40
6 17 15
20 14 24
3 17 33
8 1 47
16 18 21
20 12 98
14 15 24
6 11 49
12 6 25
3 8 18
5 7 23
12 3 82
5 15 14
20 18 7
3 6 60
17 2 477
15 2 2
8 11 257
9 2 3
5 6 3
18 1 4
12 13 269
7 9 265
6 16 2
13 2 2
5 13 6
8 13 8
14 6 8
8 14 9
17 13 7
12 10 7
16 20 31
2 6 277
4 13 426
16 9 11
10 1 388
6 1 15
20 5 3
12 19 16
16 19 2
输出样例#2
1192
数据范围
1⩽n⩽2×1051⩽m⩽2×1061⩽ai⩽263−11\leqslant n \leqslant 2\times 10^5\\1\leqslant m \leqslant 2\times 10^6\\1\leqslant a_i\leqslant 2^{63}-11⩽n⩽2×1051⩽m⩽2×1061⩽ai⩽263−1
解题思路
对于求出来的路线中,设从1到最后一个点的路径为干线(如图下图,最后一个点为5,干线为1-2-3-5)
对于干线上的边(如2-3),来回各会走两遍
而对于非干线上的边,在去的时候,要离开干线,再回到干线,共两遍
而回来的时候不用走
所以无论是干线上的边还是非干线上的边,都会走两遍
那么对该图做最小生成树,使得所有点都到过一遍,然后乘2即可
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
ll n, m, x, y, num, ans, fa[200021];
struct node
{ll x, y, l;
}a[2000021];
bool cmp(node a, node b)
{return a.l < b.l;
}
ll find(ll x)
{return x == fa[x]?x:fa[x] = find(fa[x]);
}
int main()
{scanf("%lld%lld", &n, &m);for (ll i = 1; i <= m; ++i)scanf("%lld%lld%lld", &a[i].x, &a[i].y, &a[i].l);sort(a + 1, a + 1 + m, cmp);for (ll i = 1; i <= n; ++i)fa[i] = i;num = 1;for (ll i = 1; i <= m; ++i)//最小生成树{x = find(a[i].x);y = find(a[i].y);if (x != y){num++;ans += a[i].l;//记录边权fa[x] = y;if (num == n) break;//这里要用num记录一下,如果所有点都到过了,就直接退出,以减少时间,不然会T}}printf("%lld", ans * 2);return 0;
}