您的位置:首页 > 其它

洛谷3366 最小生成树(Prim + 堆优化)

2017-07-28 21:58 295 查看

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出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

日常发板,感觉自己不是很常用的算法都没正经学……

Prim优化后的复杂度仿佛很谜啊,但这题交上去好像还是会比Kruskal快些的

代码

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
const int Maxn = 0x3f3f3f3f;
const int N = 5e4 + 5, M = 4e5 + 5;
int dis
, n, m, Ans; bool vis
;

struct Edge
{
int to, cst; Edge *nxt;
}p[M], *T = p, *lst
;

struct point
{
int s, t;
inline bool operator < (const point &x) const
{
return s < x.s;
}
point() {}
point(const int &Ss, const int &Tt):
s(Ss), t(Tt) {}
};

struct SmaRt
{
point g[M]; int len;

inline void Pop()
{
g[1] = g[len--];
int now = 1, nxt = 2; point res = g[1];
while (nxt <= len)
{
if (nxt < len && g[nxt | 1] < g[nxt]) nxt |= 1;
if (g[nxt] < res)
g[now] = g[nxt], nxt = (now = nxt) << 1;
else break;
}
g[now] = res;
}

inline void Push(const point &res)
{
g[++len] = res;
int now = len, nxt = len >> 1;
while (nxt)
{
if (res < g[nxt])
g[now] = g[nxt], nxt = (now = nxt) >> 1;
else break;
}
g[now] = res;
}
}Q;

inline void addEdge(const int &x, const int &y, const int &z)
{
(++T)->nxt = lst[x]; lst[x] = T; T->to = y; T->cst = z;
(++T)->nxt = lst[y]; lst[y] = T; T->to = x; T->cst = z;
}

inline int get()
{
char ch; int res;
while ((ch = getchar()) < '0' || ch > '9');
res = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9')
res = (res << 3) + (res << 1) + ch - '0';
return res;
}

int main()
{
n = get(); m = get(); int x, y;
while (m--)
{
x = get(); y = get();
addEdge(x, y, get());
}
memset(dis, Maxn, sizeof(dis));
Q.Push(point(dis[1] = 0, 1));
for (int i = 1; i <= n; ++i)
{
while (vis[Q.g[1].t] && Q.len) Q.Pop();
if (!Q.len) return puts("orz"), 0;
vis[x = Q.g[1].t] = true; Q.Pop();
Ans += dis[x];
for (Edge *e = lst[
4000
x]; e; e = e->nxt)
if (!vis[y = e->to] && dis[y] > e->cst)
Q.Push(point(dis[y] = e->cst, y));
}
printf("%d\n", Ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  prim 最小生成树