M的数据范围是[1,2000000],神坑1。
边两端高度相同时要建双向边,神坑2。
若边i的起点和终点未访问过,则表明边i是废边(与起点1不连通),神坑3。
那么对于添边,我们可以看做是现有一颗树,通过连接一条边将一个点加入到树里的过程
那么对于添加一个点,假设有一种方案先加入X,然后加入Y,HIGH[X]<HIGH[Y]那么肯定
可以找到另一种添加方式,先加入Y,再加入X,因为Y比X高,也就是既然能先加X,X肯定不
影响Y的合法性,也就是以高度为优先级,保证了合法性,神坑4
/**************************************************************
Problem: 2753
User: xujiahe
Language: C++
Result: Accepted
Time:12208 ms
Memory:69212 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
#define ll long long
#define maxn 2100000
int hight[maxn],p[maxn],father[maxn];
int n,m,num;
bool vis[maxn];
struct node
{
long long val;
int v,u,next;
}edge[maxn];
void build(int x,int y,long long z)
{
num++;
edge[num].v=x;
edge[num].u=y;
edge[num].val=z;
edge[num].next=p[x];
p[x]=num;
}
void bfs()
{
int ans1=0;
vis[1]=1;
queue<int>q;
q.push(1);
while(!q.empty())
{
int v=q.front();
q.pop();
ans1++;
for(int e=p[v];e;e=edge[e].next)
{
if(!vis[edge[e].u])
{
vis[edge[e].u]=1;
q.push(edge[e].u);
}
}
}
printf("%d ",ans1);
}
bool cmp(node aa,node bb)
{
return hight[aa.u]>hight[bb.u]||((hight[aa.u]==hight[bb.u])&&(aa.val<bb.val));
}
int getfather(int x)
{
if(x==father[x])
return x;
return father[x]=getfather(father[x]);
}
void kru()
{
long long ans2=0;
sort(edge+1,edge+num+1,cmp);
for(int i=1;i<=num;i++)
{
int r1=getfather(edge[i].v);
int r2=getfather(edge[i].u);
if(!vis[edge[i].v]||!vis[edge[i].u]) continue;
if(r1!=r2)
{
father[r1]=r2;
ans2+=edge[i].val;
}
}
printf("%lld",ans2);
}
int main()
{
int x,y;
long long z;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
father[i]=i;
for(int i=1;i<=n;i++)
scanf("%d",&hight[i]);
for(int i=1;i<=m;i++)
{
scanf("%d%d%lld",&x,&y,&z);
if(hight[x]>=hight[y]) build(x,y,z);
if(hight[y]>=hight[x]) build(y,x,z);
}
bfs();
kru();
return 0;
}
。