原題連結
題解
這題乍一看好像是一道最小生成樹的模板題,但如果直接找模板打會發現WA。
仔細一看這題是有向圖的最小生成樹,可以直接套朱劉演算法,but,我還不會······
直接套模板的反例
3 3 2 1 1 2 5 1 3 2 2 3 1
所以我們再分析題目,發現只要把山的高度設為第一優先順序,邊的權值為第二優先順序,再建樹即可。
code
#include<bits/stdc++.h> using namespace std; const int N=1e5+5; const int M=2e6+5; typedef long long ll; int head[N],Next[M],to[M],h[N],weight[M]; bool vis[N]; int n,m,cnt=1,sum=0; ll pre=0; struct node{ int id,value; bool operator <(const node &a)const{ if (h[id]!=h[a.id]) return h[id]<h[a.id]; return value>a.value; } }; void build(int from,int to_,int w){ Next[cnt]=head[from]; to[cnt]=to_; weight[cnt]=w; head[from]=cnt++; } void prim(int from){ priority_queue<node> que; node x; x.id=from; x.value=0; que.push(x); while (!que.empty()){ x=que.top(); que.pop(); if (vis[x.id]) continue; else vis[x.id]=true; sum++; pre+=x.value; for (int i=head[x.id];i>0;i=Next[i]){ node y; y.id=to[i]; y.value=weight[i]; que.push(y); } } } int main(){ cin>>n>>m; for (int i=1;i<=n;i++){ cin>>h[i]; } for (int i=1;i<=m;i++){ int a,b,c; cin>>a>>b>>c; if (h[a]>=h[b]) build(a,b,c); if (h[a]<=h[b]) build(b,a,c); } prim(1); cout<<sum<<" "<<pre; return 0; }