您的位置:首页 > 其它

洛谷 P3366 【模板】最小生成树

2017-10-17 20:42 351 查看

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz

输入输出格式

输入格式:

第一行包含两个整数N、M,表示该图共有 N 个结点和 M 条无向边。(N≤5000,M≤200000)

接下来 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


说明

时空限制:

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: