【BZOJ4883】棋盘上的守卫
题面
http://darkbzoj.tk/problem/4883
题解
克鲁斯卡尔维护基环森林。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define ri register int #define N 100050 using namespace std; struct edge { int u,v,l; bool operator < (const edge &rhs) const { return l<rhs.l; } } e[N]; int n,m; int cir[N<<1]; int f[N<<1]; int findroot(int x){ if (f[x]==x) return x; return f[x]=findroot(f[x]); } int main() { int c; int tt=0; scanf("%d %d",&n,&m); for (ri i=1;i<=n;i++) for (ri j=1;j<=m;j++) { scanf("%d",&c); e[++tt]=(edge){i,j+n,c}; } sort(e+1,e+tt+1); long long ans=0; for (ri i=1;i<=n+m;i++) f[i]=i; for (ri i=1;i<=tt;i++) { int r1=findroot(e[i].u),r2=findroot(e[i].v); if (cir[r1] && cir[r2]) continue; if (r1==r2) { cir[r1]=1; ans+=e[i].l; continue; } f[r2]=r1;cir[r1]|=cir[r2]; ans+=e[i].l; } cout<<ans<<endl; }