[BZOJ1977]严格次小生成树

【问题描述】

  小C最近学了很多最小生成树的算法,Prim算法、Kurskal算法、消圈算法等等。

  正当小C洋洋得意之时,小P又来泼小C冷水了。小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说:如果最小生成树选择的边集是EM,严格次小生成树选择的边集是ES,那么需要满足:(value(e)表示边e的权值) 
   这里写图片描述 
          
  这下小C蒙了,他找到了你,希望你帮他解决这个问题。

【输入格式】

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

【输出格式】

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

【输入样例】

5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6

【输出样例】

11 

【数据范围】

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

题解:

要求求严格次小生成树,首先kruskal就无法使用,prim复杂度太高

于是我们用LCA

构造出最小生成树,可知次小生成树肯定是加入某边再删去一边

假设加入(i,j)则有删去生成树上i~j路径最大的边,用倍增维护

但是严格次小没有解决

可以在用倍增维护最大值时,再维护次小值,那么当最大值等于加入边权值时则删去次大边

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 using namespace std;
  6 typedef long long lol;
  7 struct Messi
  8 {
  9     lol u,v;
 10     lol dis;
 11 }edge1[500001];
 12 struct Node
 13 {
 14     lol next,to;
 15     lol dis;
 16 }edge[100001];
 17 lol num,head[100001],set[100001],depth[100001],Max[100001][18],Max2[100001][18],fa[100001][18],n,m,ans1,ans=2e9;
 18 bool vis[100001],b[500001];
 19 bool cmp(Messi a,Messi b)
 20 {
 21     return a.dis<b.dis;
 22 }
 23 void add(lol u,lol v,lol dis)
 24 {
 25     num++;
 26     edge[num].next=head[u];
 27     head[u]=num;
 28     edge[num].to=v;
 29     edge[num].dis=dis;
 30 }
 31 lol find(lol x)
 32 {
 33     if (set[x]!=x) set[x]=find(set[x]);
 34     return set[x];
 35 }
 36 void dfs(lol x,lol dep)
 37 {int i;
 38     vis[x]=1;
 39     depth[x]=dep;
 40     for (i=1;i<=17;i++)
 41     if (dep>(1<<i))
 42     {
 43         Max[x][i]=max(Max[x][i-1],Max[fa[x][i-1]][i-1]);
 44         if (Max[x][i-1]!=Max[fa[x][i-1]][i-1]) Max2[x][i]=Max[x][i-1]+Max[fa[x][i-1]][i-1]-Max[x][i];
 45         Max2[x][i]=max(Max2[x][i],max(Max2[x][i-1],Max2[fa[x][i-1]][i-1]));
 46         fa[x][i]=fa[fa[x][i-1]][i-1];
 47     }
 48     for (i=head[x];i;i=edge[i].next)
 49     {
 50         int v=edge[i].to;
 51         if (vis[v]==0)
 52         {
 53             fa[v][0]=x;
 54             Max[v][0]=edge[i].dis;
 55             dfs(v,dep+1);
 56         }
 57     }
 58 }
 59 lol ask(lol x,lol y,lol d)
 60 {int i;
 61     lol s1=0,s2=0;
 62     if (depth[x]<depth[y]) swap(x,y);
 63     for (i=17;i>=0;i--)
 64      if ((1<<i)<=depth[x]-depth[y])
 65       {
 66           if (s1!=Max[x][i]) s2=max(s2,min(s1,Max[x][i]));
 67           s2=max(s2,Max2[x][i]);
 68           s1=max(s1,Max[x][i]);
 69        x=fa[x][i];
 70       }
 71     if (x==y) 
 72     {
 73         if (s1==d&&s2) return d-s2;
 74         else if (s2==0) return 2e9;
 75         else if (s1!=d)return d-s1;
 76     }
 77     for (i=17;i>=0;i--)
 78     {
 79       if ((1<<i)<depth[x]&&fa[x][i]!=fa[y][i])
 80         {
 81         if (s1!=Max[x][i]) s2=max(s2,min(s1,Max[x][i]));
 82           s2=max(s2,Max2[x][i]);
 83           s1=max(s1,Max[x][i]);
 84         if (s1!=Max[y][i]) s2=max(s2,min(s1,Max[y][i]));
 85           s2=max(s2,Max2[y][i]);
 86           s1=max(s1,Max[y][i]);    
 87             x=fa[x][i];y=fa[y][i];
 88         }           
 89     }
 90     if (s1!=Max[x][0]) s2=max(s2,min(s1,Max[x][0]));
 91           s2=max(s2,Max2[x][0]);
 92           s1=max(s1,Max[x][0]);
 93         if (s1!=Max[y][0]) s2=max(s2,min(s1,Max[y][0]));
 94           s2=max(s2,Max2[y][0]);
 95           s1=max(s1,Max[y][0]);
 96     x=fa[x][0];y=fa[y][0];
 97     if (s1==d&&s2) return d-s2;
 98         else if (s2==0) return 2e9;
 99         else if (s1!=d)return d-s1;
100 }
101 int main()
102 {int i,j,q,opt,x,y;
103 //freopen("scrip.in","r",stdin);
104 //freopen("scrip.out","w",stdout);
105     cin>>n>>m;
106     for (i=1;i<=m;i++)
107     {
108         scanf("%d%d%d",&edge1[i].u,&edge1[i].v,&edge1[i].dis);
109     }
110     sort(edge1+1,edge1+m+1,cmp);
111     for (i=1;i<=n;i++)
112     set[i]=i;
113     i=1;j=1;
114      while (i<=n-1&&j<=m)
115      {
116          int p=find(edge1[j].u),q=find(edge1[j].v);
117              if (p!=q)
118              {
119               set[p]=q;
120               i++;
121               b[j]=1;
122               ans1+=edge1[j].dis;
123               add(edge1[j].u,edge1[j].v,edge1[j].dis);
124               add(edge1[j].v,edge1[j].u,edge1[j].dis);
125             }
126             j++;
127      }
128      if (i<=n-1)
129      {
130          cout<<"No MST!";
131          return 0;
132      }
133      dfs(1,1);
134      for (j=1;j<=m;j++)
135      {
136           if (b[j]==0)
137           {
138                ans=min(ans,ask(edge1[j].u,edge1[j].v,edge1[j].dis));
139           } 
140      }
141     if (ans==2e9)
142     {
143         cout<<"No SST!";
144         return 0;
145     }
146 cout<<ans+ans1;
147 }

 

posted @ 2017-07-28 16:38  Z-Y-Y-S  阅读(1103)  评论(0编辑  收藏  举报