题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz
输入输出格式
输入格式:
第一行包含两个整数
N、M
,表示该图共有
N
个结点和
接下来
M
行每行包含三个整数
输出格式:
输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出 orz
输入输出样例
输入样例#1:
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出样例#1:
7
说明
时空限制:
1000ms,128M
数据规模:
对于 20% 的数据: N≤5,M≤20
对于 40% 的数据: N≤50,M≤2500
对于 70% 的数据: N≤500,M≤10000
对于 100% 的数据: N≤5000,M≤200000
样例解释:
所以最小生成树的总边权为 2+2+3=7
solution
对于 n≤1000 的数据,Prim模板题
其余的数据,Kruskal模板题
code
其实还想写堆优化的prim来着,但是没找到代码风格和我差不多的模板…sad
就先用这两个吧
还有一遍速度对比的文章,感兴趣的话可以戳这里
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
template<typename T>
void input(T &x) {
x=0; T a=1;
register char c=getchar();
for(;c<'0'||c>'9';c=getchar())
if(c=='-') a=-1;
for(;c>='0'&&c<='9';c=getchar())
x=x*10+c-'0';
x*=a;
return;
}
namespace __Prim {
const int MAXN=1000;
const int inf=2147483647;
int G[MAXN][MAXN];
int lowcost[MAXN];
bool vis[MAXN];
void Prim(int n,int m) {
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
G[i][j]=inf*(i!=j);
for(int i=1;i<=m;i++) {
int u,v,w;
input(u),input(v),input(w);
if(w<G[u][v]) G[u][v]=w;
if(w<G[v][u]) G[v][u]=w;
}
for(int i=1;i<=n;i++)
lowcost[i]=G[1][i],vis[i]=false;
vis[1]=true;
int MST=0;
for(int k=1;k<n;k++) {
int Min=inf,u=-1;
for(int i=1;i<=n;i++)
if(!vis[i]&&lowcost[i]<Min)
Min=lowcost[u=i];
if(u==-1) {
printf("orz");
return;
}
vis[u]=true;
MST+=Min;
for(int v=1;v<=n;v++)
if(!vis[v]&&lowcost[v]>G[u][v])
lowcost[v]=G[u][v];
}
printf("%d",MST);
return;
}
}
namespace __Kruskal {
const int MAXN=5010;
const int MAXM=200010;
struct Edge {
int u,v,w;
Edge(int u=0,int v=0,int w=0):
u(u),v(v),w(w) {}
bool operator < (const Edge &q) const {
return w<q.w;
}
};
Edge edge[MAXM];
int father[MAXN];
int Find(int x) {
return father[x]==x?x:father[x]=Find(father[x]);
}
bool Union(int x,int y) {
if((x=Find(x))==(y=Find(y)))
return false;
father[x]=y;
return true;
}
void Kruskal(int n,int m) {
for(int i=1;i<=m;i++)
input(edge[i].u),
input(edge[i].v),
input(edge[i].w);
for(int i=1;i<=n;i++)
father[i]=i;
sort(edge+1,edge+m+1);
int MST=0,k=0;
for(int i=1;i<=m;i++)
if(Union(edge[i].u,edge[i].v))
MST+=edge[i].w,k++;
if(k==n-1) printf("%d",MST);
else printf("orz");
return;
}
}
int main() {
int n,m;
input(n),input(m);
if(n<=1000) __Prim::Prim(n,m);
else __Kruskal::Kruskal(n,m);
return 0;
}