首先,这玩意儿像一个最小树型图。然而超大的数据让我们不得不考虑分层的kruskal。
也就是第一关键字是高度,第二关键字才是边权。
然后我们只关心从1能到达的点,而不关心整张图的最小生成树。
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<algorithm> #define maxv 100500 #define maxe 2000500 using namespace std; struct edge { long long u,v,w,nxt,h; }e[maxe]; queue <long long> q; long long n,m,r[maxv],a,b,c,nume=0,father[maxv],g[maxv]; bool vis[maxv]; bool cmp(edge x,edge y) { if (x.h!=y.h) return x.h>y.h; return x.w<y.w; } void addedge(long long u,long long v,long long w,long long h) { e[++nume].u=u; e[nume].v=v; e[nume].w=w; e[nume].h=h; e[nume].nxt=g[u]; g[u]=nume; } long long bfs() { q.push(1);vis[1]=true; while (!q.empty()) { long long head=q.front(); q.pop(); for (long long i=g[head];i;i=e[i].nxt) { long long v=e[i].v; if (vis[v]==false) { vis[v]=true; q.push(v); } } } long long ret=0; for (long long i=1;i<=n;i++) { if (vis[i]==true) ret++; father[i]=i; } return ret; } long long getfather(long long x) { if (x!=father[x]) father[x]=getfather(father[x]); return father[x]; } long long kruskal() { long long ret=0; sort(e+1,e+nume+1,cmp); for (long long i=1;i<=nume;i++) { long long u=e[i].u,v=e[i].v,w=e[i].w; if ((vis[u]) && (vis[v])) { long long f1=getfather(u),f2=getfather(v); if (f1!=f2) { father[f1]=f2; ret+=w; } } } return ret; } int main() { scanf("%lld%lld",&n,&m); for (long long i=1;i<=n;i++) scanf("%lld",&r[i]); for (long long i=1;i<=m;i++) { scanf("%lld%lld%lld",&a,&b,&c); if (r[a]>=r[b]) addedge(a,b,c,r[b]); if (r[a]<=r[b]) addedge(b,a,c,r[a]); } printf("%lld ",bfs()); printf("%lld\n",kruskal()); return 0; }