首页
登录 | 注册

【最小生成树】[Scoi2012] bzoj2753 滑雪与时间胶囊

题目点这里


像我这种出来培训也不忘刷水题的:)


orz其实这题感觉就是乱搞。。

本来写的最短路。。然后写着写着发现这tm不是一个MST吗……

果断重写 = =


只能从高到低那么就把高的边排前面就行了233

这样每一条边的起点如果可以到达 那么枚举到它的时候它就已经在树里了

然后这题就这么水过去了。。。。


最开始把k打成M = =WA了三次 T_T


#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring> 
#include <algorithm>

using namespace std;

const int Nmax = 100005;
const int Mmax = 1000005;

int N, M;
long long ans;
int cnt;

int H[Nmax];
struct ed{
    int u, v, w, next;
}e[Mmax * 2];
int k = 1, head[Nmax];

inline void adde(int u, int v, int w)
{
    e[k] = (ed) { u, v, w, head[u] };
    head[u] = k++;
}

queue <int> q;
bool vis[Nmax];

inline void bfs()
{
	q.push(1); vis[1] = 1; cnt = 1; 
	
	while(q.size())
	{
		int u = q.front(); q.pop();
		for(int i = head[u]; i; i = e[i].next)
		{
			int v = e[i].v;
			if(vis[v]) continue;
			vis[v] = 1; ++cnt;
			q.push(v);
		}
	}
}

int fa[Nmax];

inline bool cmp(ed a, ed b)
{
	if(H[a.v] != H[b.v]) return H[a.v] > H[b.v];
	return a.w < b.w;
}

int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }

inline void kruskal()
{
	for(int i = 1; i <= N; ++i) fa[i] = i;
	sort(e + 1, e + k, cmp);
	for(int i = 1; i < k; ++i)
	{
		int u = e[i].u, v = e[i].v;
		if(!vis[u] || !vis[v] || find(u) == find(v)) continue;
		fa[find(v)] = fa[find(u)]; ans += e[i].w;
	}
}

int main()
{
    scanf("%d%d", &N, &M);
    for(int i = 1; i <= N; ++i) scanf("%d", &H[i]);
    for(int i = 1; i <= M; ++i)
    {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        if(H[u] >= H[v]) adde(u, v, w);
        if(H[v] >= H[u]) adde(v, u, w);
    }
    bfs(); kruskal();
    printf("%d %I64d\n", cnt, ans);
    
    return 0;
}





2020 jeepxie.net webmaster#jeepxie.net
10 q. 0.009 s.
京ICP备10005923号