bzoj2753: [SCOI2012]滑雪与时间胶囊 MST

来源:互联网 发布:厦门seo平台 编辑:程序博客网 时间:2024/03/29 09:10

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 2100000int 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;}



0 0
原创粉丝点击