其他分享
首页 > 其他分享> > $P2573\ [SCOI2012]滑雪$

$P2573\ [SCOI2012]滑雪$

作者:互联网

$P2573\ [SCOI2012]滑雪$

\(problem\)

这题就是 搜索 + 最小生成树?

反正就是这样的

  1. 求从1开始能最到几个地方。
    2.最短长度 即最小生成树。
    我的做法是 先前向星存图 存好之后遍历 弄好第一个问 顺便处理好第二个问。
    可以搜索 遍历出来 能到几个点。 然后顺便重新存图 因为有些路径就在这时候显得一点没用了。

然后跑\(kruskal\) 求最短距离? 没了。

关于排序的话 有一点 要从高到低排 高度相同的 取最小(最小生成树)

所以的话呢
我们需要一个cmp

bool cmp(E x , E y) { return h[x.v] == h[y.v] ? x.w < y.w : h[x.v] > h[y.v] ; }

然而这样的话 就可以达到排序的目的 也就是保证拓展的点最多

关于前向星存图 注意的是 高度相等需要建双向边。

数组开两倍(大雾

#include <bits/stdc++.h>
using namespace std ;
//#define int long long 

typedef long long LL ;
inline int rd() { int x = 0 ; int f = 1 ; register char c ;
#define gc c = getchar()
    while(isspace(gc)) ;
    if(c == '-') f = -1 , gc ;
    while(x = (x<<1) + (x<<3) + (c&15) , isdigit(gc)) ;
    return x * f ;
#undef gc
}

int n , m ;
const int inf = INT_MAX >> 1 ;
const int N = 100000 + 5 ;
int h[N] ;
const int M = 1000000 + 5 ;
struct node { int to ; int val ; int nxt ; } Edge[M << 1] ;
int cnt(0) ;
int head[N] ;
struct E { int u ; int v ; int w ; } edge[M << 1] ;
bool cmp(E x , E y) { return h[x.v] == h[y.v] ? x.w < y.w : h[x.v] > h[y.v] ; }
inline void Add(int u , int v , int w) {
    Edge[++ cnt].to = v , Edge[cnt].val = w , Edge[cnt].nxt = head[u] ;
    head[u] = cnt ; 
}
int fa[N] ;
inline int find (int x) { return x == fa[x] ? x : fa[x] = find (fa[x]) ; } 
inline void merge(int x , int y) { fa[x] = y ; }
bool vis[N] ;
int num(0) , sum(1) ;
LL ans(0) ;
inline void Dfs(int x) {
    for(register int i = head[x] ; i ; i = Edge[i].nxt) {
        edge[++ num].u = x ; edge[num].v = Edge[i].to ; edge[num].w = Edge[i].val ;
        if(!vis[Edge[i].to]) vis[Edge[i].to] = 1 , ++ sum , Dfs(Edge[i].to) ;
    }
} 
inline void kruskal() {
    sort(edge + 1 , edge + num + 1 , cmp) ;
    for(register int i=1;i<=num;i++) {
        int fx = find(edge[i].u) , fy = find(edge[i].v) ;
        if(fx == fy) continue ;
        merge(fx , fy) ; ans += edge[i].w ;
    }
    return ;
}
signed main() {
    n = rd() , m = rd() ;
    for(register int i=1;i<=n;i++) fa[i] = i ;
    for(register int i=1;i<=n;i++) h[i] = rd() ;
    for(register int i=1;i<=m;i++) {
        int u = rd() , v = rd() , w = rd() ;
        if(h[u] >= h[v]) Add(u , v , w) ;
        if(h[u] <= h[v]) Add(v , u , w) ;
    }
    vis[1] = 1 , Dfs(1) ;
    kruskal() ;
    cout << sum << ' ' << ans << endl ;
    return 0 ;
}
posted @ 2019-04-22 22:50 breezeღ 阅读(...) 评论(...) 编辑 收藏

标签:num,int,edge,fa,Edge,inline,滑雪,P2573,SCOI2012
来源: https://blog.csdn.net/qq_42628055/article/details/89464316