BZOJ2753 [SCOI2012]滑雪与时间胶囊 【kruskal】

题目链接

BZOJ2753

题解

完了我连\(kruskal\)裸题都做不出来了。。

题目是求最小树形图,即有向图最小生成树
我们不能直接上\(kruskal\),而要保证先加入前面的点,
所以我们排序的时候第一关键字改为高度即可

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 1000005,maxm = 2000005,INF = 1000000000;
inline int read(){
    int out = 0,flag = 1; char c = getchar();
    while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    return out * flag;
}
int high[maxn],n,m;
int h[maxn],ne;
struct EDGE{int from,to,nxt; LL w;}ed[maxm];
inline void build(int u,int v,LL w){
    ed[++ne] = (EDGE){u,v,h[u],w}; h[u] = ne;
}
int tot;
struct edge{int a,b; LL w;}e[maxm];
inline bool operator <(const edge& a,const edge& b){
    return high[a.b] == high[b.b] ? a.w < b.w : high[a.b] > high[b.b];
}
int vis[maxn],q[maxn],head,tail,N;
void bfs(){
    q[head = tail = 0] = 1; vis[1] = true; N = 1;
    int u;
    while (head <= tail){
        u = q[head++];
        Redge(u) if (!vis[to = ed[k].to]){
            N++; vis[to] = true; q[++tail] = to;
        }
    }
}
int pre[maxn];
int find(int u){return u == pre[u] ? u : pre[u] = find(pre[u]);}
void kruskal(){
    for (int i = 1; i <= n; i++) pre[i] = i;
    LL ans = 0; int cnt = N,fa,fb;
    sort(e + 1,e + 1 + tot);
    for (int i = 1; i <= tot && cnt > 1; i++){
        fa = find(e[i].a); fb = find(e[i].b);
        if (fa != fb){
            pre[fb] = fa;
            cnt--;
            ans += e[i].w;
        }
    }
    printf("%d %lld\n",N,ans);
}
int main(){
    n = read(); m = read();
    for (int i = 1; i <= n; i++) high[i] = read();
    int a,b,w;
    for (int i = 1; i <= m; i++){
        a = read(); b = read(); w = read();
        if (high[a] >= high[b]) build(a,b,w);
        if (high[b] >= high[a]) build(b,a,w);
    }
    bfs();
    for (int i = 1; i <= ne; i++){
        if (vis[ed[i].from] && vis[ed[i].to])
            e[++tot] = (edge){ed[i].from,ed[i].to,ed[i].w};
    }
    kruskal();
    return 0;
}

posted @ 2018-05-20 21:18  Mychael  阅读(125)  评论(0编辑  收藏  举报