• bzoj1977


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

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 3001  Solved: 751
    [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 。

    Source

    首先我们要知道次小生成树是最小生成树删掉一条边并加上一条边,那么枚举每条边,通过倍增计算最小边和次小边,计算答案即可。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> PII;
    #define N 100010
    struct edge
    {
        int to,nxt,w;
    }e[N*6];
    struct edge1 
    {
        int u,v,w;
    };
    vector<edge1> E;
    int n,m,cnt=1;
    ll tot;
    int head[N],father[N],dep[N],mark[N];
    int fa[N][23];
    ll maxcost[N][23];
    ll max(ll x,ll y)
    {
        return x>y?x:y;
    }
    ll min(ll x,ll y)
    {
        return x<y?x:y;
    }
    bool cp(edge1 x,edge1 y)
    {
        return x.w<y.w;
    }
    void link(int u,int v,int w)
    {
        e[++cnt].nxt=head[u];
        head[u]=cnt;
        e[cnt].to=v;
        e[cnt].w=w;
    }
    int find(int u)
    {
        return u==father[u]?father[u]:find(father[u]);
    }
    void connect(int u,int v)
    {
        int a=find(u);
        int b=find(v);
        if(a==b) return;
        father[a]=b;
    }
    void dfs(int u,int Fa)
    {
        for(int i=head[u];i;i=e[i].nxt) if(e[i].to!=Fa)
        {
            int v=e[i].to;
            dep[v]=dep[u]+1;
            fa[v][0]=u;
            maxcost[v][0]=e[i].w;
            dfs(v,u);
        }
    }
    PII lca(int u,int v)
    {
        PII ret;
        if(dep[u]<dep[v]) swap(u,v);
        for(int i=22;i>=0;i--) if((dep[u]-dep[v])&(1<<i)) 
        {
            if(maxcost[u][i]>ret.first)
            {
                ret.second=ret.first;
                ret.first=maxcost[u][i];
            }
            else if(maxcost[u][i]<ret.first)
                ret.second=max(ret.second,maxcost[u][i]);
            u=fa[u][i];
        }
        if(u==v) return ret;
        for(int i=22;i>=0;i--) if(fa[u][i]!=fa[v][i]) 
        {
            if(maxcost[u][i]>ret.first)
            {
                ret.second=ret.first;
                ret.first=maxcost[u][i];
            }
            else if(maxcost[u][i]<ret.first)
                ret.second=max(ret.second,maxcost[u][i]);
            if(maxcost[v][i]>ret.first)
            {
                ret.second=ret.first;
                ret.first=maxcost[v][i];
            }
            else if(maxcost[v][i]<ret.first)
                ret.second=max(ret.second,maxcost[v][i]);
            u=fa[u][i]; v=fa[v][i];
        }
        if(maxcost[u][0]>ret.first)
        {
            ret.second=ret.first;
            ret.first=maxcost[u][0];
        }
        else if(maxcost[u][0]<ret.first)
            ret.second=max(ret.second,maxcost[u][0]);
        if(maxcost[v][0]>ret.first)
        {
            ret.second=ret.first;
            ret.first=maxcost[v][0];
        }
        else if(maxcost[v][0]<ret.first)
            ret.second=max(ret.second,maxcost[v][0]);
        return ret;
    }
    void build()
    {
        for(int i=1;i<=22;i++)
            for(int j=1;j<=n;j++) if(fa[j][i-1]!=-1)
            {
                fa[j][i]=fa[fa[j][i-1]][i-1];
                maxcost[j][i]=max(maxcost[j][i-1],
                maxcost[fa[j][i-1]][i-1]);
            }
    }
    void kruskal()
    {
        sort(E.begin(),E.end(),cp);
        for(int i=1;i<=n;i++) father[i]=i;
        for(int i=0;i<E.size();i++) if(find(E[i].u)!=find(E[i].v))
        {
            connect(E[i].u,E[i].v);
            mark[i]=1;
            tot+=E[i].w;
            link(E[i].u,E[i].v,E[i].w);
            link(E[i].v,E[i].u,E[i].w);
        }
        dfs(1,1);
        build();
        ll ans=(ll)(1e17);
        for(int i=0;i<E.size();i++) if(!mark[i])
        {
            PII x=lca(E[i].u,E[i].v);
            if(x.first<E[i].w) ans=min(ans,tot+E[i].w-x.first);
            else if(x.first==E[i].w) ans=min(ans,tot+E[i].w-x.second);
        }
        printf("%lld",ans);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int u,v,w; scanf("%d%d%d",&u,&v,&w);
            edge1 x;
            x.u=u; x.v=v; x.w=w;
            E.push_back(x);
        }
        kruskal();
        return 0;
    }
  • 相关阅读:
    RN-Android构建失败:Caused by: org.gradle.api.ProjectConfigurationException: A problem occurred configuring root project 'AwesomeProject'.
    Android更新包下载成功后不出现安装界面
    真机调试: The application could not be installed: INSTALL_FAILED_TEST_ONLY
    react native 屏幕尺寸转换
    Android Studio生成签名文件,自动签名,以及获取SHA1和MD5值
    React Native安卓真机调试
    git提交代码报错Permission denied, please try again
    The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.
    命令行设置快捷命令
    Linux 常用指令
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6286355.html
Copyright © 2020-2023  润新知