[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

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

bzoj1977 [BeiJing2010组队]次小生成树 Tree——严格次小生成树

[Beijing2010组队]次小生成树Tree

[BeiJing2010组队]次小生成树 Tree

洛谷P4180 [Beijing2010组队]次小生成树Tree