1 条题解
-
0
题解
滑雪只能沿着高度不升的轨道前进,因此我们先从 1 号景点出发做一次 BFS,仅保留满足
H[u] ≥ H[v]
的有向边,把所有能够到达的景点标记出来;这些点的数量就是可以游览的最大景点数。随后只在这个可达子图上考虑轨道,针对每条原始无向边按照高度关系至多保留一个方向(高→低),并按“终点高度从高到低、同高度下长度从小到大”的顺序排序。这样用 Kruskal 在这些有向边上生成一棵(或若干棵)最小生成树,就能保证在覆盖全部可达景点的前提下,滑行总距离最小。由于时间胶囊可以让滑雪者在树上随意回溯,树结构即可满足行程需要,输出的就是最多可达景点数以及对应的最短滑行距离和。// 只能从点权大的点到小的点,于是这么建边 // 那么显然我们需要的是一个树形结构,这样每条边最多走一次 // 那么搜索出所有能到达的点再Kruscal? // 在落点高度相同的情况下,我们优先选择边权最小的 // 否则我们必须考虑更高的,以保证正确性 //#define DEBUG #ifdef DEBUG #include<iostream> #include<cstdio> #include<cstdlib> #include<time.h> #include<string.h> #include<memory.h> #include<random> #include<unordered_map> #include<set> #include<map> #include<vector> #include<queue> #include<deque> #include<algorithm> #endif #ifndef DEBUG #include<bits/stdc++.h> #endif using namespace std; bool MEMST; int clock_st = clock(); #define ll long long #define ull unsigned long long #define pii pair<ll,ll> #define pb push_back #define fi first #define se second #define il inline #define reg register #define ld long double #define fastio ios::sync_with_stdio(false), cin.tie(0) #define LEFT (POS*2) #define RIGHT (POS*2+1) #define lc(x) tr[x].l ? tr[x].l : tr[x].l=++tlt #define rc(x) tr[x].r ? tr[x].r : tr[x].r=++tlt #define lll __int128 mt19937_64 engine(time(0)); const ll N = 1e5+5; const ll M = 2e6+5; vector<pii> E[N]; ll n,m,H[N],tlt,fa[N]; struct Edge{ ll u,v,w; il bool operator <(const Edge &ano){ if(H[v] == H[ano.v]) return w < ano.w; return H[v] > H[ano.v]; } } Edges[M], G[M]; bool bfsvis[N]; il void bfs(){ queue<ll> Q; bfsvis[1]=1; Q.push(1); while(!Q.empty()){ ll u=Q.front(); Q.pop(); for(pii ed : E[u]){ ll v=ed.fi, w=ed.se; if(bfsvis[v]) continue; bfsvis[v]=1; Q.push(v); } } return ; } il ll find(ll x){ if(fa[x]!=x) fa[x]=find(fa[x]); return fa[x]; } il void unity(ll tx, ll ty){ ll fa1=find(tx), fa2=find(ty); if(fa1==fa2) return ; fa[fa1] = fa2; return ; } il pii Kruscal(){ ll ans1=0,ans2=0; sort(G+1, G+tlt+1); for(ll i=1; i<=n; i++){ fa[i]=i; if(bfsvis[i]) ans1++; } for(ll i=1; i<=tlt; i++){ ll u=G[i].u, v=G[i].v, w=G[i].w; if(find(u)==find(v)) continue; unity(u, v); ans2 += w; } return {ans1, ans2}; } bool MEMED; signed main() { fastio; cin >> n >> m; for(ll i=1; i<=n; i++) cin >> H[i]; for(ll i=1; i<=m; i++){ ll u,v,k; cin >> u >> v >> k; Edges[i] = {u,v,k}; if(H[u]>=H[v]) E[u].pb({v,k}); if(H[v]>=H[u]) E[v].pb({u,k}); } bfs(); for(ll i=1; i<=m; i++){ if(bfsvis[Edges[i].u] && bfsvis[Edges[i].v]){ ll u=Edges[i].u, v=Edges[i].v, w=Edges[i].w; if(H[u]>=H[v]) G[++tlt] = {u,v,w}; if(H[u]<=H[v]) G[++tlt] = {v,u,w}; } } pii ans = Kruscal(); printf("%lld %lld\n", ans.fi, ans.se); #ifdef DEBUG printf("time: %lld ms\n", (ll)(((double)clock() - clock_st) * 1000.0 / CLOCKS_PER_SEC)); printf("memory: %.2lf MB\n", (double)abs((&MEMED - &MEMST) / 1024.0 / 1024.0)); #endif return 0; }
- 1
信息
- ID
- 3248
- 时间
- 3000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者