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

    题解:和cf的一道题比较类似 首先跑一个MST 对于这个树做树链剖分 枚举不在这个树上的边找严格小于这条边的最大边权值 然后求ans

    #include <bits/stdc++.h>
    #define ll long long
    const int MAXN=1e5+10;
    const int maxn=3e5+10;
    const int inf=1e9+20;
    using namespace std;
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f*x;
    }
    vector<pair<int,int> >vec[MAXN];
    typedef struct Edge{
        int u,v,vul;bool flag;
        friend bool operator<(Edge aa,Edge bb){return aa.vul<bb.vul;}
    }Edge;
    Edge edge[maxn];
    int n,m,f[MAXN];
    int find1(int x){
        if(f[x]==x)return x;
        else return f[x]=find1(f[x]);
    }
    int key[MAXN],fa[MAXN],dep[MAXN],num[MAXN],son[MAXN];
    void dfs(int v,int pre,int deep){
        dep[v]=deep+1;num[v]=1;fa[v]=pre;
        for(int i=0;i<vec[v].size();i++){
    	int u=vec[v][i].first;
    	if(u!=pre){
    	    key[u]=vec[v][i].second;
    	    dfs(u,v,deep+1);
    	    num[v]+=num[u];
    	    if(son[v]==-1||num[son[v]]<num[u])son[v]=u;
    	}
        }
    }
    int tp[MAXN],cnt,p[MAXN],fp[MAXN];
    void dfs1(int v,int td){
        p[v]=++cnt;fp[p[v]]=v;tp[v]=td;
        if(son[v]!=-1)dfs1(son[v],td);
        for(int i=0;i<vec[v].size();i++){
    	if(vec[v][i].first!=fa[v]&&vec[v][i].first!=son[v])dfs1(vec[v][i].first,vec[v][i].first);
        }
    }
    int maxx[MAXN<<2],maxx1[MAXN<<2];
    void up(int x){
        maxx[x]=max(maxx[x<<1],maxx[x<<1|1]);
        maxx1[x]=maxx1[x<<1];
        if(maxx[x<<1]!=maxx[x])maxx1[x]=max(maxx1[x],maxx[x<<1]);
        if(maxx[x<<1|1]!=maxx[x])maxx1[x]=max(maxx1[x],maxx[x<<1|1]);
        if(maxx1[x<<1|1]!=maxx[x])maxx1[x]=max(maxx1[x],maxx1[x<<1|1]);
    }
    void built(int rt,int l,int r){
        if(l==r){maxx[rt]=key[fp[l]];maxx1[rt]=-1;return ;}
        int mid=(l+r)>>1;
        built(rt<<1,l,mid);
        built(rt<<1|1,mid+1,r);
        up(rt);
    }
    int ans1;
    void querty(int rt,int l,int r,int ql,int qr,int vul){
        if(ql<=l&&r<=qr){
    	if(maxx[rt]==vul)ans1=max(ans1,maxx1[rt]);
    	else ans1=max(ans1,maxx[rt]);
    	return ;
        }
        int mid=(l+r)>>1;
        if(ql<=mid)querty(rt<<1,l,mid,ql,qr,vul);
        if(qr>mid)querty(rt<<1|1,mid+1,r,ql,qr,vul);
    }
    int slove(int u,int v,int t){
        int uu=tp[u];int vv=tp[v];
        ans1=-1*inf;
        while(uu!=vv){
    	if(dep[uu]<dep[vv])swap(uu,vv),swap(u,v);
    	querty(1,1,n,p[uu],p[u],t);
    	u=fa[uu];uu=tp[u];
        }
        if(dep[u]>dep[v])swap(u,v);
        if(u!=v)querty(1,1,n,p[son[u]],p[v],t);
        return ans1;
    }
    int main(){
        n=read();m=read();int u,v,vul;
        for(int i=1;i<=m;i++)edge[i].u=read(),edge[i].v=read(),edge[i].vul=read();
        for(int i=1;i<=n;i++)f[i]=i,son[i]=-1;
        sort(edge+1,edge+m+1);ll ans=0;
        for(int i=1;i<=m;i++){
    	int t1=find1(edge[i].u);
    	int t2=find1(edge[i].v);
    	if(t1==t2)continue;
    	ans+=edge[i].vul;
    	f[t1]=t2;vec[edge[i].u].push_back(make_pair(edge[i].v,edge[i].vul));
    	vec[edge[i].v].push_back(make_pair(edge[i].u,edge[i].vul));edge[i].flag=1;
        }
        //cout<<ans<<endl;
        dfs(1,0,0);dfs1(1,1);built(1,1,n);
       // cout<<"sb"<<endl;
        ll ans2=1e18;
        for(int i=1;i<=m;i++){
    	if(edge[i].flag)continue;
    	vul=slove(edge[i].u,edge[i].v,edge[i].vul);
    	if(vul<0)continue;
    	ans2=min(ans2,ans-vul+1ll*edge[i].vul);
        }
        printf("%lld
    ",ans2);
        return 0;
    }
    

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

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 3853  Solved: 1104
    [Submit][Status][Discuss]

    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 。

  • 相关阅读:
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之六 多点触控
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之九 定位
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之七 重力感应
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之五 保存数据的几种方式
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之八 照相机
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之三 Application 配置详解
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之四 打开与关闭应用程序是的保存数据
    ADOBE FLASH BUILDER 4.6 IOS 开发之部署与调试
    [译] 高性能JavaScript 1至5章总结
    页签及盒子的web标准实现
  • 原文地址:https://www.cnblogs.com/wang9897/p/9343678.html
Copyright © 2011-2022 走看看