bzoj1977 [BeiJing2010组队]次小生成树 倍增
来源:互联网 发布:网络运维工程师招聘 编辑:程序博客网 时间:2024/06/08 05:01
标准的次小生成树(严格次小)
先想想不严格怎么做(好像都差不多)
枚举每一条边来更新,这是n^2算法。
然后这题的话我们对于每一个点,预处理,倍增一下求他到他的第2^j个父亲所经过的边的最大值和次大值。
然后我们先求出最小生成树,然后对于最小生成树上相邻两个点之间所有边,记录最大值和所选的边的差,如果最大值和原来的边相等就换成次大值,最后答案就是最小生成树+最小差值。
#include<cstdio>#include<algorithm>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=3e5+5;int head[N],f[N],dep[N],fa[N][17];int d1[N][17],d2[N][17];const int inf=0x7fffffff;struct node{ int x,y,z; bool sel;}a[N];int next[N],go[N],val[N];int tot,n,m,cnt,mn=inf;;typedef long long ll;ll ans;bool cmp(node a,node b){ return a.z<b.z;}inline void add(int x,int y,int z){ go[++tot]=y; val[tot]=z; next[tot]=head[x]; head[x]=tot;} inline void ins(int x,int y,int z){ add(x,y,z); add(y,x,z);}inline int find(int x){ return x==f[x]?x:find(f[x]);}inline void dfs(int x,int f){ fo(i,1,16) { if (dep[x]<(1<<i))break; fa[x][i]=fa[fa[x][i-1]][i-1]; d1[x][i]=max(d1[x][i-1],d1[fa[x][i-1]][i-1]); if (d1[x][i-1]==d1[fa[x][i-1]][i-1]) d2[x][i]=max(d2[x][i-1],d2[fa[x][i-1]][i-1]); else { d2[x][i]=min(d1[x][i-1],d1[fa[x][i-1]][i-1]); d2[x][i]=max(d2[x][i-1],d2[x][i]); d2[x][i]=max(d2[x][i],d2[fa[x][i-1]][i-1]); } } for(int i=head[x];i;i=next[i]) { int v=go[i]; if (v!=f) { fa[v][0]=x; d1[v][0]=val[i]; dep[v]=dep[x]+1; dfs(v,x); } }}inline int lca(int x,int y){ if (dep[x]<dep[y])swap(x,y); fd(i,16,0) if (dep[fa[x][i]]>=dep[y])x=fa[x][i]; if (x==y)return x; fd(i,16,0) if (fa[x][i]!=fa[y][i]) { x=fa[x][i]; y=fa[y][i]; } return fa[x][0];}inline void cal(int x,int f,int v){ int mx1=0,mx2=0; int t=dep[x]-dep[f]; fo(i,0,16) { if (t&(1<<i)) { if(d1[x][i]>mx1) { mx2=mx1; mx1=d1[x][i]; } mx2=max(mx2,d2[x][i]); x=fa[x][i]; } } if (mx1!=v)mn=min(mn,v-mx1); else mn=min(mn,v-mx2);}inline void solve(int t,int v){ int x=a[t].x,y=a[t].y,f=lca(x,y); cal(x,f,v),cal(y,f,v);}int main(){ scanf("%d%d",&n,&m); fo(i,1,n)f[i]=i; fo(i,1,m)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); sort(a+1,a+1+m,cmp); int count=0; fo(i,1,m) { int fx=find(a[i].x),fy=find(a[i].y); if (fx!=fy) { f[fx]=fy; ans+=a[i].z; a[i].sel=1; ins(a[i].x,a[i].y,a[i].z); count++; if (count==n-1)break; } } dfs(1,0); fo(i,1,m) if (!a[i].sel)solve(i,a[i].z); printf("%lld\n",ans+mn);}
阅读全文
0 0
- bzoj1977: [BeiJing2010组队]次小生成树 Tree 树上倍增
- bzoj1977 [BeiJing2010组队]次小生成树 倍增
- bzoj1977 [BeiJing2010组队]次小生成树 Tree (lca+倍增)
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree Kruskal+倍增LCA
- [BZOJ1977][Beijing2010组队][LCA][Kruskal]次小生成树
- bzoj1977: [BeiJing2010组队]次小生成树 Tree
- bzoj1977: [BeiJing2010组队]次小生成树 Tree
- BZOJ1977: [BeiJing2010组队]次小生成树 Tree
- bzoj1977 [BeiJing2010组队]次小生成树 Tree
- BZOJ1977: [BeiJing2010组队]次小生成树 Tree
- BZOJ1977 [BeiJing2010组队] [次小生成树 Tree]
- bzoj1977 [BeiJing2010]次小生成树 Tree(kruskal+树上倍增)
- bzoj1977: [BeiJing2010]次小生成树 kruskal+倍增LCA
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree【次小生成树】【LCA】
- 1977: [BeiJing2010组队]次小生成树 Tree kruskal+倍增
- [BZOJ1977][BeiJing2010组队]次小生成树 Tree(kruskal+链剖)
- 【BZOJ1977】【MST】【LCA】[BeiJing2010组队]次小生成树 Tree 题解
- bzoj 1977: [BeiJing2010组队]次小生成树 Tree 最小生成树+倍增
- Random方法,列表元组的使用
- Git查看、删除、重命名远程分支和tag
- springboot动态修改系统日志级别
- hashmap、hashtable、ConCurrentHashMap分析
- poj 3186 && bzoj 1652: [Usaco2006 Feb]Treats for the Cows(DP)
- bzoj1977 [BeiJing2010组队]次小生成树 倍增
- Paper:Learning from Imbalanced Data
- JAVA Runtime.addShutdownHook()方法
- U3D移动平台的资源路径问题
- cs231n-之训练过程参数监控(占个位,回来补)
- Eclipse下导入外部jar包的3种方式
- spring支持五种事务隔离和六种事务传播属性
- java.lang.IndexOutOfBoundsException: Index: 4, Size: 4
- 数组和运算符简介