BZOJ2753 滑雪与时间胶囊 (洛谷P2573)

来源:互联网 发布:俄罗斯军粮淘宝 编辑:程序博客网 时间:2024/05/01 10:48

最小生成树

BZOJ题目传送门
洛谷传送门

因为可以无限制地使用时间胶囊,所以第一问直接BFS跑跑就行啦
第二问的话对边按高度为第一关键字,权值为第二关键字排个序,然后Kruskal乱搞一下就行啦
注意:
对边排序时应该按目标节点的高度排序。因为建边时就已经保证初始节点的高度大于等于目标节点,这样排的话就可以保证初始节点已经被做过,不会让程序乱跑。反正50秒时间很充裕。(洛谷的时限1s简直有毒)(貌似现在改5秒了,于是我就A了)。

贴上代码:

#include<cstdio>#include<cstring>#include<algorithm>#define MAXN 100000#define MAXM 1000000using namespace std;struct edge{    int now;    int next;    int to;    int dis;};int k,n,m,u,v,d,num;long long ans=0;edge a[2*MAXM+5];int b[MAXN+5],que[MAXN+5],father[MAXN+5],h[MAXN+5];bool f[MAXN+5];void bfs(){    int r=0,w=1;    que[1]=1; f[1]=true; num=1;    while (r<w){        int x=que[++r];        for (int i=h[x];i;i=a[i].next){            if (!f[a[i].to]){                que[++w]=a[i].to;                num++;                f[a[i].to]=true;            }        }    }}void read(int x,int y,int z){    k++; a[k].now=x; a[k].next=h[x]; a[k].to=y; a[k].dis=z;    h[x]=k;}bool comp(edge x,edge y){    if ((b[x.to]>b[y.to])||(b[x.to]==b[y.to]&&x.dis<y.dis))        return true;    return false;}int findfather(int x){    if (x==father[x])        return x;    else{        father[x]=findfather(father[x]);        return father[x];    }}int main(){    scanf("%d%d",&n,&m);    for (int i=1;i<=n;i++){        scanf("%d",&b[i]);        father[i]=i;    }    for (int i=1;i<=m;i++){        scanf("%d%d%d",&u,&v,&d);        if (b[u]>=b[v]) read(u,v,d);        if (b[v]>=b[u]) read(v,u,d);    }    bfs();    printf("%d ",num);    sort(a+1,a+k+1,comp);    for (int i=1;i<=k;i++){        if (!f[a[i].now]||!f[a[i].to])            continue;        int fx=findfather(a[i].now),fy=findfather(a[i].to);        if (fx!=fy){            father[fx]=fy;            ans+=a[i].dis;        }    }    printf("%lld\n",ans);    return 0;}
阅读全文
1 0
原创粉丝点击