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

    www.cnblogs.com/shaokele/


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

      Time Limit: 10 Sec
      Memory Limit: 512 MB

    Description###

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

    题目地址:  bzoj 1977: [BeiJing2010组队]次小生成树 Tree

    题目大意:   求严格次小的生成树

    题解:

      水题         md写了两个小时
      先求出最⼩⽣成树
      对于每条不在最小生成树的边(u,v,w),求出最⼩⽣成树中,u,v之间最⼤值,若最⼤值等于w,则找严格次⼤值
      最⼤值与次⼤值,都可以通过树上倍增来处理
      数据下载 bzoj 1977


    AC代码

    #include <cstdio>
    #include <algorithm>
    #define ll long long
    using namespace std;
    const int N=1e5+5,M=3e5+5;
    int n,m,cnt,stmax,ndmax;
    int f[N],last[N],dep[N],fa[N][18],g[N][18],G[N][18];
    ll res;
    bool vis[N],flag[M];
    struct edge{
    	int u,v,w;
    }e[M];
    struct star{
    	int u,v,w,next;
    }E[N+N];
    void add_edge(int u,int v,int w){
    	E[++cnt]=(star){u,v,w,last[u]};last[u]=cnt;
    	E[++cnt]=(star){v,u,w,last[v]};last[v]=cnt;
    }
    int find(int x){
        while(x!=f[x])x=f[x]=f[f[x]];
        return x;
    }
    bool cmp(edge a,edge b){
        return a.w<b.w;
    }
    void Kurskal(){
    	int cnt=0;
        sort(e+1,e+m+1,cmp);
        for(int i=1;i<=m;i++){
            int fu=find(e[i].u);
            int fv=find(e[i].v);
            if(fu==fv)continue;
            flag[i]=1;
            add_edge(e[i].u,e[i].v,e[i].w);
            res+=e[i].w;
            f[fv]=fu;
            if(++cnt==n-1)return;
        }
    }
    void dfs(int u,int father){
    	if(vis[u])return;vis[u]=1;
    	dep[u]=dep[father]+1;
    	for(int i=last[u];i;i=E[i].next){
    		int v=E[i].v;
    		dfs(v,u);
    		fa[v][0]=u;
    		g[v][0]=E[i].w;
    		G[v][0]=-1;
    	}
    }
    int lca(int a,int b){
    	if(dep[a]<dep[b])swap(a,b);
    	int t=dep[a]-dep[b];
    	for(int i=17;i>=0;i--)
    		if((1<<i)&t)a=fa[a][i];
    	for(int i=17;i>=0;i--)
    		if(fa[a][i]!=fa[b][i])
    			a=fa[a][i],b=fa[b][i];
    	if(a==b)return a;
    	return fa[a][0];
    }
    void calc(int a,int b){
    	int t=dep[a]-dep[b];
    	for(int i=17;i>=0;i--)
    		if((1<<i)&t){
    			if(g[a][i]>stmax){
    				ndmax=stmax;
    				stmax=g[a][i];
    			}
    			ndmax=max(ndmax,G[a][i]);
    			a=fa[a][i];
    		}
    }
    void solve(int a,int b,int top){
    	calc(a,top);calc(b,top);
    }
    int main(){
    	scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            f[i]=i;
        for(int i=1;i<=m;i++)
            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        Kurskal();
        
        dfs(1,0);
        for(int j=1;j<=17;j++)
        	for(int i=1;i<=n;i++){
        		fa[i][j]=fa[fa[i][j-1]][j-1];
        		g[i][j]=max(g[i][j-1],g[fa[i][j-1]][j-1]);
        		
        		if(g[i][j-1]!=g[fa[i][j-1]][j-1])
    				G[i][j]=min(g[i][j-1],g[fa[i][j-1]][j-1]);
    			G[i][j]=max(G[i][j],max(G[i][j-1],G[fa[i][j-1]][j-1]));
    		}
    
    	ll ans=1e14+5;
    	for(int i=1;i<=m;i++)
    		if(!flag[i]){
    			int top=lca(e[i].u,e[i].v);
    			stmax=ndmax=-1;
    			solve(e[i].u,e[i].v,top);
    			if(stmax!=e[i].w)
    				ans=min(ans,res-stmax+e[i].w);
    			else
    			 	ans=min(ans,res-ndmax+e[i].w);
    		}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    java经典面试题
    用OpenSSL把二进制的Cer证书转换程Base64格式的PEM格式的证书
    JVM中java实例对象在内存中的布局
    高级加密标准(英语:Advanced Encryption Standard,缩写:AES)
    中断和中断处理程序
    CS 寄存器 和 IP 寄存器
    Gson通过借助TypeToken获取泛型参数的类型的方法
    Tomcat 的 JDBC 连接池
    Google Guava官方教程(中文版)
    阿里DRUID数据源
  • 原文地址:https://www.cnblogs.com/shaokele/p/9336585.html
Copyright © 2011-2022 走看看