zoukankan      html  css  js  c++  java
  • BZOJ1977: [BeiJing2010组队]次小生成树 Tree

    1977: [BeiJing2010组队]次小生成树 Tree

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 2108  Solved: 463
    [Submit][Status]

    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 。

    Source

    题解:

    真是不能再sb了。。。数组越界+xy打反。。。

    如果不是严格的只需要枚举每条边,在MST上找这两点之间最大的边记作x,与当前枚举边的权值记作y,用y-x更新答案即可。

    但是如果是严格的话?就会出现y==x的情况,那我们可以不管这条边吗?

    当然不行,次小生成树是由MST加上一条边删去另一条边得到的。

    想想看如果去掉此时两点间的次大值,加上y,也有可能成为答案。第三大就不会了。

    所以我们需要找次大边,分情况来更新答案。

    我还有点不懂的地方就是:

    不同的两个MST最多有多少条边不同?怎么保证任何一个MST通过本题的操作都能的得到正确的答案?

    求神犇指教。

    代码:

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<iostream>
      7 #include<vector>
      8 #include<map>
      9 #include<set>
     10 #include<queue>
     11 #include<string>
     12 #define inf 1000000000
     13 #define maxn 100000+100
     14 #define maxm 300000+100
     15 #define eps 1e-10
     16 #define ll long long
     17 #define pa pair<int,int>
     18 #define for0(i,n) for(int i=0;i<=(n);i++)
     19 #define for1(i,n) for(int i=1;i<=(n);i++)
     20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     21 using namespace std;
     22 inline int read()
     23 {
     24     int x=0,f=1;char ch=getchar();
     25     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     26     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     27     return x*f;
     28 }
     29 int dep[maxn],fa[maxn],head[maxn],tot,n,m,f[maxn][22];
     30 bool out[maxm];
     31 struct recc{int a,b;} g[maxn][22],ret;
     32 struct edge{int go,next,w;}e[2*maxn];
     33 struct rec{int x,y,z;}a[maxm];
     34 inline void insert(int x,int y,int w)
     35 {
     36     e[++tot].go=y;e[tot].w=w;e[tot].next=head[x];head[x]=tot;
     37     e[++tot].go=x;e[tot].w=w;e[tot].next=head[y];head[y]=tot;
     38 }
     39 inline bool cmp(rec a,rec b)
     40 {
     41     return a.z<b.z;
     42 }
     43 inline void update(recc &x,recc &y)
     44 {
     45     if(y.a<x.a)y.b=y.a,y.a=x.a;
     46         else {if(x.a>y.b&&x.a<y.a)y.b=x.a;}
     47     if(x.b==-1)return;
     48     if(y.a<x.b)y.b=y.a,y.a=x.b;
     49         else {if(x.b>y.b&&x.b<y.a)y.b=x.b;}    
     50 }            
     51 inline void dfs(int x)
     52 {
     53     for1(i,20)
     54      if((1<<i)<=dep[x])
     55       {
     56         f[x][i]=f[f[x][i-1]][i-1];
     57         g[x][i].a=g[x][i].b=-1;  
     58         update(g[f[x][i-1]][i-1],g[x][i]);
     59         update(g[x][i-1],g[x][i]);      
     60       }
     61      else break;
     62     for(int i=head[x],y;i;i=e[i].next)
     63       if(!dep[y=e[i].go])
     64       {
     65         f[y][0]=x;g[y][0].a=e[i].w;g[y][0].b=-1;
     66         dep[y]=dep[x]+1;
     67         dfs(y);
     68       }
     69 }
     70 inline void query(int x,int y)
     71 {
     72     if(dep[x]<dep[y])swap(x,y);
     73     int t=dep[x]-dep[y];
     74     ret.a=ret.b=-1;
     75     for0(i,20)
     76      if(t&(1<<i))
     77       {
     78         update(g[x][i],ret);
     79         x=f[x][i];
     80       }
     81     if(x==y)return;
     82     for(int i=20;i>=0;i--)
     83      if(f[x][i]!=f[y][i])
     84       {
     85           
     86         update(g[x][i],ret);x=f[x][i];
     87         update(g[y][i],ret);y=f[y][i];
     88       }  
     89     update(g[x][0],ret);update(g[y][0],ret); 
     90 }
     91 inline int find(int x)
     92 {
     93     return fa[x]==x?x:fa[x]=find(fa[x]);
     94 }
     95 int main()
     96 {
     97     freopen("input.txt","r",stdin);
     98     freopen("output.txt","w",stdout);
     99     n=read();m=read();
    100     for1(i,m)a[i].x=read(),a[i].y=read(),a[i].z=read();
    101     sort(a+1,a+m+1,cmp);
    102     for1(i,n)fa[i]=i;
    103     ll sum=0,ans=inf;
    104     for(int i=1,j=1;i<=n-1;i++)
    105      {
    106         while(find(a[j].x)==find(a[j].y))j++;
    107         fa[find(a[j].x)]=find(a[j].y);insert(a[j].x,a[j].y,a[j].z);
    108         out[j]=1;
    109         sum+=a[j].z;j++;
    110      }
    111     dep[1]=1;g[1][0].a=g[1][0].b=-1;
    112     dfs(1);
    113     for1(i,m)if(!out[i])
    114     {
    115         int x=a[i].x,y=a[i].y,z=a[i].z;query(x,y);
    116         if(ret.a!=z&&z-ret.a<ans)ans=z-ret.a;
    117         if(ret.a==z&&ret.b!=-1&&z-ret.b<ans)ans=z-ret.b;
    118     }
    119     printf("%lld
    ",ans+sum);
    120     return 0;
    121 }
    View Code
  • 相关阅读:
    创建基于MailKit和MimeKit的.NET基础邮件服务
    MailKit---获取邮件
    C# 与JAVA 的RSA 加密解密交互,互通,C#使用BouncyCastle来实现私钥加密,公钥解密的方法
    .net 开源 FTP 组件 edtFTPnet
    Consul1-window安装consul
    通信传输利器Netty(Net is DotNetty)介绍
    工作中,如何衡量一个人的 JavaScript 编码水平?
    10个有趣又能编译为JavaScript的语言,你用过哪些?
    一定要你明白Java中的volatile
    面试总被问到HTTP缓存机制及原理?看完你就彻底明白了
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/3963223.html
Copyright © 2011-2022 走看看