像我这种出来培训也不忘刷水题的:)
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;
}