[BJOI 2010]次小生成树Tree
Posted NaVi_Awson
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BJOI 2010]次小生成树Tree相关的知识,希望对你有一定的参考价值。
Description
小 C 最近学了很多最小生成树的算法,Prim 算法、Kurskal 算法、消圈算法等等。 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了。小 P 说,让小 C 求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说: 如果最小生成树选择的边集是 EM,严格次小生成树选择的边集是 ES,那么需要满足:(value(e) 表示边 e的权值) 这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。
Input
第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z。
Output
包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)
Sample Input
5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
Sample Output
11
Hint
数据中无向图无自环; 50% 的数据N≤2 000 M≤3 000; 80% 的数据N≤50 000 M≤100 000; 100% 的数据N≤100 000 M≤300 000 ,边权值非负且不超过 10^9 。
题解
次小生成树模板。简便地直接用LCA做。唯一注意的是由于它要求严格的次小生成树,所以我们LCA时还要记得保存次大值。(防止边权相等)
1 #include<map> 2 #include<cmath> 3 #include<ctime> 4 #include<queue> 5 #include<stack> 6 #include<cstdio> 7 #include<string> 8 #include<cstring> 9 #include<cstdlib> 10 #include<iostream> 11 #include<algorithm> 12 #define LL long long 13 using namespace std; 14 const LL N=100000; 15 16 LL n,m,op,x,y,p,q,d=2e15; 17 struct aa 18 { 19 LL u,v,c; 20 }lin[N*3+5]; 21 bool comp(aa a,aa b); 22 23 LL mst,cnt; 24 struct bb 25 { 26 LL to,next,cost; 27 }edge[N*2+5]; 28 LL path[N+5],top; 29 bool vis[N*3+5]; 30 void Add(LL u,LL v,LL c); 31 32 LL set[N+5]; 33 LL Find(LL x); 34 35 LL f[N+5][20],maxn[N+5][20],sub[N+5][20]; 36 LL dep[N+5]; 37 void Dfs(LL x,LL depth); 38 void Lca(LL x,LL y,LL c); 39 40 int main() 41 { 42 scanf("%lld%lld",&n,&m); 43 op=log2(n); 44 for (LL i=1;i<=m;i++) scanf("%lld%lld%lld",&lin[i].u,&lin[i].v,&lin[i].c); 45 sort(lin+1,lin+m+1,comp); 46 for (LL i=1;i<=m;i++) 47 { 48 p=Find(lin[i].u); 49 q=Find(lin[i].v); 50 if (p!=q) 51 { 52 set[p]=q; 53 cnt++; 54 mst+=lin[i].c; 55 vis[i]=1; 56 Add(lin[i].u,lin[i].v,lin[i].c); 57 Add(lin[i].v,lin[i].u,lin[i].c); 58 if (cnt==n-1) break; 59 } 60 } 61 if (cnt<n-1) 62 { 63 printf("No MST!\n"); 64 return 0; 65 } 66 Dfs(1,1); 67 for (LL t=1;t<=op;t++) 68 for (LL i=1;i<=n;i++) 69 if (f[i][t-1]) 70 { 71 f[i][t]=f[f[i][t-1]][t-1]; 72 x=maxn[i][t-1];y=sub[i][t-1]; 73 p=maxn[f[i][t-1]][t-1];q=sub[f[i][t-1]][t-1]; 74 if (x==p){maxn[i][t]=x;sub[i][t]=max(y,q);} 75 else if (x>p){maxn[i][t]=x;sub[i][t]=max(p,y);} 76 else if (x<p){maxn[i][t]=p;sub[i][t]=max(x,q);} 77 } 78 for (LL i=1;i<=m;i++) if (!vis[i]) Lca(lin[i].u,lin[i].v,lin[i].c); 79 if (d==2e15) printf("No SST!"); 80 else printf("%lld\n",mst+d); 81 return 0; 82 } 83 84 bool comp(aa a,aa b){return a.c<b.c;} 85 void Add(LL u,LL v,LL c) 86 { 87 edge[++top].to=v; 88 edge[top].next=path[u]; 89 edge[top].cost=c; 90 path[u]=top; 91 } 92 LL Find(LL x){return set[x] ? set[x]=Find(set[x]):x;} 93 void Dfs(LL x,LL depth) 94 { 95 dep[x]=depth; 96 for (LL i=path[x];i;i=edge[i].next) if (!dep[edge[i].to]) 97 { 98 f[edge[i].to][0]=x; 99 maxn[edge[i].to][0]=edge[i].cost; 100 Dfs(edge[i].to,depth+1); 101 } 102 } 103 void Lca(LL x,LL y,LL c) 104 { 105 LL m1=0,m2=0; 106 if (dep[x]<dep[y]) swap(x,y); 107 for (LL i=op;i>=0;i--) if (dep[x]-(1<<i)>=dep[y]) 108 { 109 if (sub[x][i]>m1){m2=m1;m1=sub[x][i];} 110 else if (sub[x][i]>m2&&sub[x][i]!=m1) m2=sub[x][i]; 111 if (maxn[x][i]>m1){m2=m1;m1=maxn[x][i];} 112 else if (maxn[x][i]>m2&&maxn[x][i]!=m1) m2=maxn[x][i]; 113 x=f[x][i]; 114 } 115 if (x!=y) 116 { 117 for (LL i=op;i>=0;i--) if (f[x][i]!=f[y][i]) 118 { 119 if (sub[x][i]>m1){m2=m1;m1=sub[x][i];} 120 else if (sub[x][i]>m2&&sub[x][i]!=m1) m2=sub[x][i]; 121 if (maxn[x][i]>m1){m2=m1;m1=maxn[x][i];} 122 else if (maxn[x][i]>m2&&maxn[x][i]!=m1) m2=maxn[x][i]; 123 if (sub[y][i]>m1){m2=m1;m1=sub[y][i];} 124 else if (sub[y][i]>m2&&sub[y][i]!=m1) m2=sub[y][i]; 125 if (maxn[y][i]>m1){m2=m1;m1=maxn[y][i];} 126 else if (maxn[y][i]>m2&&maxn[y][i]!=m1) m2=maxn[y][i]; 127 x=f[x][i]; 128 y=f[y][i]; 129 } 130 if (sub[x][0]>m1){m2=m1;m1=sub[x][0];} 131 else if (sub[x][0]>m2&&sub[x][0]!=m1) m2=sub[x][0]; 132 if (maxn[x][0]>m1){m2=m1;m1=maxn[x][0];} 133 else if (maxn[x][0]>m2&&maxn[x][0]!=m1) m2=maxn[x][0]; 134 if (sub[y][0]>m1){m2=m1;m1=sub[y][0];} 135 else if (sub[y][0]>m2&&sub[y][0]!=m1) m2=sub[y][0]; 136 if (maxn[y][0]>m1){m2=m1;m1=maxn[y][0];} 137 else if (maxn[y][0]>m2&&maxn[y][0]!=m1) m2=maxn[y][0]; 138 } 139 if (m1==0) return; 140 if (c==m1) 141 { 142 if (m2==0) return; 143 d=min(d,c-m2); 144 } 145 else d=min(d,c-m1); 146 }
以上是关于[BJOI 2010]次小生成树Tree的主要内容,如果未能解决你的问题,请参考以下文章
bzoj1977 [BeiJing2010组队]次小生成树 Tree
bzoj1977 [BeiJing2010组队]次小生成树 Tree