[SCOI2012]滑雪
题目
点这里看题目。
分析
首先第一问非常简单,可以直接 BFS 解决。
考虑第二问,类似于生成树,可以暴力朱刘算法解决显然我们只需要对 BFS 中遇到的点和边进行生成树。这里的边需要保证有 \(h_u\ge h_v\) 。
注意到这些点是必选的,因此我们只需要保证在生成树构建的过程中总有加入的边是合法的,就可以把边近似地看作无向边。
因此可以直接对于每条边,按照终点高度优先从高到低、边权次之由低到高排序并进行 Kruskal 。
由于可到的点必然可以按照高度分层,因此我们实际上是在分层进行 Kruskal ,所以每次每条边的起点必然已经被加入。
小结:
利用高度带来的层的性质,将有向边转化为无向边,从而可以进行 Kruskal 。
代码
#include
#include
using namespace std;
#define rep( i, a, b ) for( int (i) = (a) ; (i) <= (b) ; ++ (i) )
#define per( i, a, b ) for( int (i) = (a) ; (i) >= (b) ; -- (i) )
typedef long long LL;
const int MAXN = 2e5 + 5, MAXM = 1e6 + 5;
template
void read( _T &x )
{
x = 0; char s = getchar(); int f = 1;
while( s < '0' || '9' < s ) { f = 1; if( s == '-' ) f = -1; s = getchar(); }
while( '0' <= s && s <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ); s = getchar(); }
x *= f;
}
template
void write( _T x )
{
if( x < 0 ) putchar( '-' ), x = -x;
if( 9 < x ) write( x / 10 );
putchar( x % 10 + '0' );
}
template
void swapp( _T &x, _T &y )
{
_T t = x; x = y, y = t;
}
struct Edge
{
int to, nxt;
}Graph[MAXM];
struct KruEdge
{
int u, v, w, ed;
KruEdge() { u = v = w = 0; }
KruEdge( int U, int V, int W ) { u = U, v = V, w = W; }
bool operator < ( const KruEdge &b ) const { return ed == b.ed ? w < b.w : ed > b.ed; }
}E[MAXM];
int q[MAXN];
int head[MAXN], fa[MAXN], H[MAXN];
int N, M, K, cnt = 0;
bool vis[MAXN];
void MakeSet( const int siz ) { rep( i, 1, N ) fa[i] = i; }
int FindSet( const int u ) { return fa[u] = ( fa[u] == u ? u : FindSet( fa[u] ) ); }
bool UnionSet( int u, int v )
{
u = FindSet( u ), v = FindSet( v );
if( u == v ) return false; fa[u] = v; return true;
}
void AddEdge( const int from, const int to )
{
Graph[++ cnt].to = to, Graph[cnt].nxt = head[from];
head[from] = cnt;
}
int main()
{
read( N ), read( M );
rep( i, 1, N ) read( H[i] );
rep( i, 1, M )
{
read( E[i].u ), read( E[i].v ), read( E[i].w );
if( H[E[i].u] < H[E[i].v] ) continue;
AddEdge( E[i].u, E[i].v ), E[i].ed = H[E[i].v];
}
int h = 1, t = 0; vis[q[++ t] = 1] = true;
while( h <= t )
{
int u = q[h ++], v;
for( int i = head[u] ; i ; i = Graph[i].nxt )
if( ! vis[v = Graph[i].to] ) vis[q[++ t] = v] = true;
}
write( t ), putchar( ' ' ); LL ans = 0;
sort( E + 1, E + 1 + M ); MakeSet( N );
rep( i, 1, M )
if( H[E[i].u] >= H[E[i].v] )
if( vis[E[i].u] && vis[E[i].v] && UnionSet( E[i].u, E[i].v ) )
ans += E[i].w;
write( ans ), putchar( '\n' );
return 0;
}