【UOJ】176 新年的繁荣【多路增广生成树】
来源:互联网 发布:互联网泡沫 知乎 编辑:程序博客网 时间:2024/05/12 05:29
题目链接: 新年的繁荣
题目大意:任意两点之间边的边权是两点点权的与,求边权和最大生成树
题目分析:每一次对一个连通块找一条出边(不连向自己),边权最大的同时所连的连通块编号最小,这些边去重后一定不会形成环,且每次至少减少一半的连通块,因此迭代复杂度为
#include <bits/stdc++.h>using namespace std ;typedef pair < int , int > pii ;typedef long long LL ;#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 100005 ;struct Seg { int u , v , c ; Seg () {} Seg ( int u , int v , int c ) : u ( u ) , v ( v ) , c ( c ) {}} ;Seg S[MAXN] ;int top ;int nxt[MAXN * 100][2] , minv[MAXN * 100] , maxv[MAXN * 100] , cur ;int val[MAXN] ;pii to[MAXN] ;int p[MAXN] ;int n , m ;int F ( int x ) { return p[x] == x ? x : ( p[x] = F ( p[x] ) ) ;}int newnode () { nxt[cur][0] = nxt[cur][1] = 0 ; minv[cur] = MAXN ; maxv[cur] = 0 ; return cur ++ ;}void insert ( int v , int idx ) { int o = 0 ; for ( int i = m - 1 ; ~i ; -- i ) { int x = v >> i & 1 ; if ( !nxt[o][x] ) nxt[o][x] = newnode () ; o = nxt[o][x] ; if ( idx < minv[o] ) minv[o] = idx ; if ( idx > maxv[o] ) maxv[o] = idx ; }}int merge ( int x , int y ) { if ( !x && !y ) return 0 ; if ( !x ) return y ; if ( !y ) return x ; int o = cur ++ ; minv[o] = min ( minv[x] , minv[y] ) ; maxv[o] = max ( maxv[x] , maxv[y] ) ; nxt[o][0] = merge ( nxt[x][0] , nxt[y][0] ) ; nxt[o][1] = merge ( nxt[x][1] , nxt[y][1] ) ; return o ;}void dfs ( int o ) { if ( nxt[o][0] ) dfs ( nxt[o][0] ) ; if ( nxt[o][1] ) dfs ( nxt[o][1] ) ; nxt[o][0] = merge ( nxt[o][0] , nxt[o][1] ) ;}pii query ( int v , int idx ) { int res = 0 , o = 0 ; for ( int i = m - 1 ; ~i ; -- i ) { int x = v >> i & 1 ; int t = nxt[o][1] ; if ( x && t && ( minv[t] != idx || maxv[t] != idx ) ) { res |= 1 << i ; o = nxt[o][1] ; } else o = nxt[o][0] ; } return pii ( res , maxv[o] != idx ? maxv[o] : minv[o] ) ;}void solve () { for ( int i = 1 ; i <= n ; ++ i ) { scanf ( "%d" , &val[i] ) ; p[i] = i ; } int cnt = n - 1 ; LL ans = 0 ; while ( cnt ) { cur = 0 ; newnode () ; //printf ( "%d\n" , cnt ) ; for ( int i = 1 ; i <= n ; ++ i ) { if ( i == F ( i ) ) to[i] = pii ( -1 , 0 ) ; insert ( val[i] , p[i] ) ; } dfs ( 0 ) ; for ( int i = 1 ; i <= n ; ++ i ) { to[p[i]] = max ( to[p[i]] , query ( val[i] , p[i] ) ) ; } top = 0 ; for ( int i = 1 ; i <= n ; ++ i ) { if ( p[i] == i ) S[top ++] = Seg ( i , to[i].second , to[i].first ) ; } for ( int i = 0 ; i < top ; ++ i ) { int x = F ( S[i].u ) ; int y = F ( S[i].v ) ; if ( x != y ) { p[x] = y ; ans += S[i].c ; -- cnt ; } } } printf ( "%lld\n" , ans ) ;}int main () { while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ; return 0 ;}
压缩后代码:
#include <bits/stdc++.h>using namespace std;typedef pair<int,int>pii;typedef long long LL;#define clr(a,x)memset(a,x,sizeof a)const int MAXN=100005;struct Seg{ int u,v,c; Seg(){} Seg(int u,int v,int c):u(u),v(v),c(c){}}S[MAXN];int nxt[MAXN*100][2],minv[MAXN*100],maxv[MAXN*100],cur,val[MAXN],p[MAXN],n,m,top;pii to[MAXN];int F(int x){return p[x]==x?x:(p[x]=F(p[x]));}int newnode(){ nxt[cur][0]=nxt[cur][1]=0; minv[cur]=MAXN; maxv[cur]=0; return cur++;}void insert(int v,int idx){ for(int i=m-1,o=0;~i;--i){ int x=v>>i&1; if(!nxt[o][x])nxt[o][x]=newnode(); o=nxt[o][x]; if(idx<minv[o])minv[o]=idx; if(idx>maxv[o])maxv[o]=idx; }}int merge(int x,int y){ if(!x||!y)return x?x:y; int o=cur++; minv[o]=min(minv[x],minv[y]); maxv[o]=max(maxv[x],maxv[y]); nxt[o][0]=merge(nxt[x][0],nxt[y][0]); nxt[o][1]=merge(nxt[x][1],nxt[y][1]); return o;}void dfs(int o){ if(nxt[o][0])dfs(nxt[o][0]); if(nxt[o][1])dfs(nxt[o][1]); nxt[o][0]=merge(nxt[o][0],nxt[o][1]);}pii query(int v,int idx){ int res=0,o=0; for(int i=m-1;~i;--i){ int x=v>>i&1,t=nxt[o][1]; if(x&&t&&(minv[t]!=idx||maxv[t]!=idx))res|=1<<i,o=nxt[o][1]; else o=nxt[o][0]; } return pii(res,maxv[o]!=idx?maxv[o]:minv[o]);}void solve(LL ans=0){ for(int i=1;i<=n;p[i]=i,++i)scanf("%d",&val[i]); for(int cnt=n-1,i;cnt;){ for(cur=0,newnode(),i=1;i<=n;insert(val[i],p[i]),++i)if(i==F(i))to[i]=pii(-1,0); for(dfs(0),i=1;i<=n;++i)to[p[i]]=max(to[p[i]],query(val[i],p[i])); for(top=0,i=1;i<=n;++i)if(p[i]==i)S[top++]=Seg(i,to[i].second,to[i].first); for(i=0;i<top;++i){ int x=F(S[i].u),y=F(S[i].v); if(x!=y)p[x]=y,ans+=S[i].c,--cnt; } } printf("%lld\n",ans);}int main(){ while(~scanf("%d%d",&n,&m))solve(); return 0;}
0 0
- 【UOJ】176 新年的繁荣【多路增广生成树】
- [AND最大生成树 分治 Trie || Kruskal] UOJ Goodbye Yiwei C #176. 新年的繁荣
- UOJ 67 新年的毒瘤
- UOJ#67 新年的毒瘤(Tarjan算法求割点)
- uoj#67. 新年的毒瘤(割顶)
- UOJ 67 新年的毒瘤 (tarjan算法求割点)
- wustoj(二叉树的繁荣度)
- 基于增广路的网络流算法
- 最大流的增广路算法比较
- 最大流的增广路模板
- 无线互联网的繁荣
- 竞争:繁荣的硬道理
- 最小费用流 SPFA 多路增广
- dinic模板 当前弧+多路增广
- [欧拉回路 最小生成树] UOJ#236 -- IOI2016. railroad
- POJ 3281 网络流(dinic邻接矩阵、单路增广、多路增广)
- poj1459Power Network_最大流的增广路算法_多源点多汇点问题(Edmord_Karp)
- BZOJ 3280: 小R的烦恼 费用流 多路增广
- 顺丰科技面试
- kettle之导出excel数据
- Gradle多环境配置
- 初次见面,请多指教——单片机
- androidStudio V4包冲突问题以及解决方案
- 【UOJ】176 新年的繁荣【多路增广生成树】
- 单词计数
- 一个Sqrt函数引发的血案
- 算法--快速排序
- 三级缓存的理解
- curl设置代理,快速下载国外网页
- 使用Photoview实现图片左右滑动及缩放功能
- linux环境源代码安装软件的步骤
- Hive初识入门