题解:AT_codefestival_2016_final_g Zigzag MST
乱胡奇怪做法,过了,发现是黑,吓出心脏病,我应该不能独立切黑的吧?
看题解,每个我都看不懂,都不是我的做法。遂写题解。
图灵托梦告诉我,将题目描述的加边方式改为:
给定
x,y,z ,对于每个0 \le i ,加边(x+i,y+i,z+2i) ,点仍然是模n 意义下的。
这样原题的加边方式就可以拆成
考虑模拟 Kruscal 过程,对于每个加边描述,可以用一个优先队列逐步扩展
如果某个描述
简要证明:每个描述对于某个
因此一旦不能连边就跳过,如果能连边就连来构建 MST。每个加边模式最多失效被跳过
直接看代码就理解了。
#include<bits/stdc++.h>
using namespace std;
int n,m,fa[200020],cnt;
long long ans;
int gtf(int x){
return fa[x]==x?x:fa[x]=gtf(fa[x]);
}
priority_queue<pair<int,pair<int,int> > > q;
int main(){
cin.tie(0)->sync_with_stdio(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++){
int x,y,z;
cin>>x>>y>>z;
q.push({-z,{x,y}});
q.push({-(z+1),{(x+1)%n,y}});
}
while(q.size()){
int w=-q.top().first,u=q.top().second.first,v=q.top().second.second;
q.pop();
int fu=gtf(u),fv=gtf(v);
if(fu!=fv){
fa[fu]=fv;
ans+=w;
cnt++;
if(cnt==n-1)break;
q.push({-(w+2),{(u+1)%n,(v+1)%n}});
}
}
assert(cnt==n-1);
cout<<ans;
return 0;
}