题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz
。
输入格式
第一行包含两个整数 N,M,表示该图共有 N 个结点和 M 条无向边。
接下来 M 行每行包含三个整数 Xi,Yi,Zi,表示有一条长度为 Zi 的无向边连接结点 Xi,Yi。
输出格式
如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出 orz
。
输入输出样例
输入 #1
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出 #1
7
说明/提示
数据规模:
- 对于 20% 的数据,N≤5,M≤20。
- 对于 40% 的数据,N≤50,M≤2500。
- 对于 70% 的数据,N≤500,M≤1e4。
- 对于 100% 的数据:1≤N≤5000,1≤M≤2×1e5,1≤Zi≤1e4。
样例解释
所以最小生成树的总边权为 2+2+3=7。
思路:
并查集+贪心
代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 2e5+10;
int n,m;
struct Edge{
int u,v,w;
}e[N];
int fa[N];
bool compare(const Edge &a,const Edge &b)
{
return a.w < b.w;
}
int find(int i)
{
if(fa[i] != i)
{
fa[i] = find(fa[i]);
}
return fa[i];
}
bool check(int u,int v)
{
int root_u = find(u);
int root_v = find(v);
return root_v == root_u;
}
void set(int u,int v)
{
int root_u = find(u);
int root_v = find(v);
if(root_u != root_v)
{
fa[root_v] = root_u;
}
}
int MST()
{
int sum = 0,cnt = 0;
sort(e + 1,e + 1 + m,compare);
for(int i = 1 ; i <= n ; i++)
fa[i] = i;
for(int i = 1 ; i <= m ; i++)
{
int u = e[i].u;
int v = e[i].v;
int w = e[i].w;
if(!check(u,v))
{
set(u,v);//连接
sum += w;
cnt++;
}
}
if(cnt < n -1)
return -1;
else
return sum;
}
int main(void)
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for(int i = 1 ; i <= m ; i++)
{
cin >> e[i].u >> e[i].v >> e[i].w;
}
int ans = MST();
if(ans == -1)
cout << "orz";
else
cout << ans;
return 0;
}