BZOJ 2753 滑雪与时间胶囊

Posted on 2016-04-26 20:16  ziliuziliu  阅读(134)  评论(0编辑  收藏  举报

首先,这玩意儿像一个最小树型图。然而超大的数据让我们不得不考虑分层的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;
}