「LuoguP4180」 模板严格次小生成树[BJWC2010](倍增 LCA Kruscal

Posted qwerta

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「LuoguP4180」 模板严格次小生成树[BJWC2010](倍增 LCA Kruscal相关的知识,希望对你有一定的参考价值。

 

题目描述

小C最近学了很多最小生成树的算法,Prim算法、Kurskal算法、消圈算法等等。正当小C洋洋得意之时,小P又来泼小C冷水了。小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说:如果最小生成树选择的边集是EM,严格次小生成树选择的边集是ES,那么需要满足:(value(e)表示边e的权值) sum_{e in E_M}value(e)<sum_{e in E_S}value(e)eEM??value(e)<eES??value(e)

这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。

输入输出格式

输入格式:

 

第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z。

 

输出格式:

 

包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)

 

输入输出样例

输入样例#1: 复制
5 6
1 2 1 
1 3 2 
2 4 3 
3 5 4 
3 4 3 
4 5 6 
输出样例#1: 复制
11

说明

数据中无向图无自环; 50% 的数据N≤2 000 M≤3 000; 80% 的数据N≤50 000 M≤100 000; 100% 的数据N≤100 000 M≤300 000 ,边权值非负且不超过 10^9 。

题解

话说这个还没有经典到当模板吧qwq

先做一个最小生成树,图被分成树边和非树边。

在这个树上随便找个点当根,预处理好倍增的东西(包括往上$2^j$步的祖先编号,往祖先走的这条路上最长的边,这条路上第二长的边

然后把每条非树边跑一遍,设两点为$u,v$。

可以想到,从$u$到$v$的这条树上路径中找一条最大但小于这条非树边的边替换,这样的结果是严格次小生成树的一个备选结果。

所以就一边求lca一边跟那一段的最长边和第二长边对比啊什么的。

//记录第二长边主要是防止最长边和这条非树边一样长

作为紫题非常好写,非常不容易错。(毕竟只是倍增lca和Kruscal揉到一起的一个东西,元件都不难写qwq

但确实很长就是了qwq

  1 /*
  2  qwerta 
  3 P4180 【模板】严格次小生成树[BJWC2010] Accepted 
  4 100
  5 代码 C++,2.72KB
  6 提交时间 2018-10-31 19:50:25
  7 耗时/内存 1812ms, 35376KB
  8 */
  9 #include<algorithm>
 10 #include<iostream>
 11 #include<cstring>
 12 #include<cstdio>
 13 #include<cmath>
 14 using namespace std;
 15 inline int read()
 16 {
 17     char ch=getchar();
 18     int x=0;
 19     while(!isdigit(ch))ch=getchar();
 20     while(isdigit(ch)){x=x*10+ch-0;ch=getchar();}
 21     return x;
 22 }
 23 const int MAXN=1e5+3,MAXM=3e5+3;
 24 struct emm{
 25     int x,y,l,tag;
 26 }b[MAXM];
 27 bool cmp(emm qaq,emm qwq){
 28     return qaq.l<qwq.l;
 29 }
 30 int fa[MAXN];
 31 int fifa(int x)
 32 {
 33     if(fa[x]==x)return x;
 34     return fa[x]=fifa(fa[x]);
 35 }
 36 struct ahh{
 37     int e,f,l;
 38 }a[2*MAXN];
 39 int h[MAXN];
 40 int tot=0;
 41 void con(int x,int y,int l)
 42 {
 43     a[++tot].f=h[x];
 44     h[x]=tot;
 45     a[tot].e=y;
 46     a[tot].l=l;
 47     a[++tot].f=h[y];
 48     h[y]=tot;
 49     a[tot].e=x;
 50     a[tot].l=l;
 51     return;
 52 }
 53 int w[MAXN],d[MAXN];
 54 void dfs(int x)
 55 {
 56     for(int i=h[x];i;i=a[i].f)
 57     if(!d[a[i].e])
 58     {
 59         fa[a[i].e]=x;
 60         d[a[i].e]=d[x]+1;
 61         w[a[i].e]=a[i].l;
 62         dfs(a[i].e);
 63     }
 64     return;
 65 }
 66 int f[MAXN][21];
 67 int mac[MAXN][21];
 68 int macc[MAXN][21];
 69 int zz[MAXN];
 70 bool cmpp(int qaq,int qwq){
 71     return qaq>qwq;
 72 }
 73 int main()
 74 {
 75     //freopen("a.in","r",stdin);
 76     int n=read(),m=read();
 77     for(int i=1;i<=m;++i)
 78     {
 79         b[i].x=read(),b[i].y=read(),b[i].l=read();
 80     }
 81     sort(b+1,b+m+1,cmp);
 82     for(int i=1;i<=n;++i)
 83     fa[i]=i;
 84     int k=n-1,j=0;
 85     long long sum=0;
 86     while(k)
 87     {
 88         j++;
 89         int u=fifa(b[j].x),v=fifa(b[j].y);
 90         if(u!=v)
 91         {
 92             fa[u]=v;
 93             //cout<<b[j].x<<" "<<b[j].y<<" "<<b[j].l<<endl;
 94             b[j].tag=1;
 95             sum+=b[j].l;
 96             con(b[j].x,b[j].y,b[j].l);
 97             k--;
 98         }
 99     }
100     memset(fa,0,sizeof(fa));
101     int s=min(n,7);
102     d[s]=1;
103     dfs(s);
104     for(int i=1;i<=n;++i)
105     {
106         // /cout<<i<<" "<<fa[i]<<endl;
107         f[i][0]=fa[i];
108         mac[i][0]=w[i];
109     }
110     for(int j=1;j<=14;++j)
111     for(int i=1;i+(1<<j)-1<=n;++i)
112     {
113         f[i][j]=f[f[i][j-1]][j-1];
114         zz[1]=mac[i][j-1],zz[2]=macc[i][j-1];
115         zz[3]=mac[f[i][j-1]][j-1],zz[4]=macc[f[i][j-1]][j-1];
116         //cout<<zz[1]<<" "<<zz[2]<<" "<<zz[3]<<" "<<zz[4]<<endl;
117         sort(zz+1,zz+5,cmpp);
118         unique(zz+1,zz+5);
119         mac[i][j]=zz[1];
120         macc[i][j]=zz[2];
121         //cout<<i<<" "<<j<<" "<<f[i][j]<<" "<<mac[i][j]<<" "<<macc[i][j]<<endl;
122     }
123     long long ans=1e14+2333;
124     for(int i=1;i<=m;++i)
125     if(!b[i].tag)
126     {
127         int u=b[i].x,v=b[i].y;
128         if(d[u]<d[v])swap(u,v);
129         for(int j=14;j>=0;--j)
130         if(d[u]-d[v]>=(1<<j))
131         {
132             if(b[i].l>mac[u][j])
133             ans=min(ans,sum-mac[u][j]+b[i].l);
134             else if(b[i].l==mac[u][j])
135             ans=min(ans,sum-macc[u][j]+b[i].l);
136             u=f[u][j];
137         }
138         if(u==v)continue;
139         for(int j=14;j>=0;--j)
140         if(f[u][j]!=f[v][j])
141         {
142             if(b[i].l>mac[u][j])
143             ans=min(ans,sum-mac[u][j]+b[i].l);
144             else if(b[i].l==mac[u][j])
145             ans=min(ans,sum-macc[u][j]+b[i].l);
146             u=f[u][j];
147             if(b[i].l>mac[v][j])
148             ans=min(ans,sum-mac[v][j]+b[i].l);
149             else if(b[i].l==mac[v][j])
150             ans=min(ans,sum-macc[v][j]+b[i].l);
151             v=f[v][j];
152         }
153         if(b[i].l>w[u])
154         ans=min(ans,sum-w[u]+b[i].l);
155         if(b[i].l>w[v])
156         ans=min(ans,sum-w[v]+b[i].l);
157     }
158     cout<<ans<<endl;
159     return 0;
160 }

 

以上是关于「LuoguP4180」 模板严格次小生成树[BJWC2010](倍增 LCA Kruscal的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P4180 模板严格次小生成树[BJWC2010]

洛谷 P4180 模板严格次小生成树[BJWC2010]次小生成树

P4180 模板严格次小生成树[BJWC2010]

P4180 模板严格次小生成树[BJWC2010]

luogu P4180 模板严格次小生成树[BJWC2010]

P4180 模板严格次小生成树[BJWC2010]