[Boruvka算法 曼哈顿距离最大生成树] 省选模拟赛 4 C. 树树树 mst

来源:互联网 发布:linux execl函数 编辑:程序博客网 时间:2024/05/21 07:13

题目大意 求曼哈顿距离最大生成树 n100000

Boruvka算法是什么呢
这里写图片描述

也就是说 我们只要每次求一个连通块连出去的最远的边 把这些边都加入
只要这样 O(logn)就能得到一棵最大生成树

每次求两个连通块之间最大边的时候,就是求 |xixj|+|yiyj| 的最大值,分情况用set维护即可。

但是神犇是这么说的

T3,其实可以打prim,O(nlogn),快排的log……

#include<cstdio>#include<cstdlib>#include<algorithm>#include<set>#include<vector>using namespace std;typedef long long ll;typedef pair<ll,int> abcd;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void read(int &x){  char c=nc(),b=1;  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int N=100005;const int dx[]={1,-1,1,-1};const int dy[]={-1,-1,1,1};set<abcd> Set[4];int n; ll Ans=0;int x[N],y[N];ll a[N][4];int fat[N];#define pb push_backvector<int> g[N];inline int Fat(int u){  return fat[u]==u?u:fat[u]=Fat(fat[u]);}inline bool Merge(int x,int y){  x=Fat(x); y=Fat(y); if (x==y) return 0;  for (int i=0;i<(int)g[x].size();i++) g[y].pb(g[x][i]);  g[x].clear();  fat[x]=y; return 1; }struct edge{  int u,v,w;  edge(int u=0,int v=0,int w=0):u(u),v(v),w(w) { }}ed[N];int pnt=0;int main(){  freopen("mst.in","r",stdin);  freopen("mst.out","w",stdout);  read(n);  for (int i=1;i<=n;i++){    read(x[i]); read(y[i]);    for (int j=0;j<4;j++){      a[i][j]=x[i]*dx[j]+y[i]*dy[j];      Set[j].insert(abcd(a[i][j],i));    }  }  for (int i=1;i<=n;i++) fat[i]=i,g[i].pb(i);  Ans=0;  while (1){    int flag=0; pnt=0;    for (int i=1;i<=n;i++){      if (fat[i]!=i) continue;      if (g[i].size()==n){    flag=1; break;      }      for (int j=0;j<(int)g[i].size();j++)    for (int k=0;k<4;k++)      Set[k].erase(abcd(a[g[i][j]][k],g[i][j]));      ll Max=-1LL<<40,v;      for (int k=0;k<4;k++){    ll maxu=-1LL<<40,maxv;    for (int j=0;j<(int)g[i].size();j++)      if (a[g[i][j]][k]>=maxu)        maxu=a[g[i][j]][k];    set<abcd>::iterator it=Set[k^3].end(); it--;    maxv=it->first;    if (maxu+maxv>=Max)      Max=maxu+maxv,v=it->second;      }      ed[++pnt]=edge(i,v,Max);      for (int j=0;j<(int)g[i].size();j++)    for (int k=0;k<4;k++)      Set[k].insert(abcd(a[g[i][j]][k],g[i][j]));    }    if (flag) break;    for (int j=1;j<=pnt;j++)      if (Merge(ed[j].u,ed[j].v))    Ans+=ed[j].w;  }  printf("%lld\n",Ans);  return 0;}
0 0
原创粉丝点击