zoukankan      html  css  js  c++  java
  • Codeforces Educational Codeforces Round 3 E. Minimum spanning tree for each edge 树上倍增

    E. Minimum spanning tree for each edge

    题目连接:

    http://www.codeforces.com/contest/609/problem/E

    Description

    Connected undirected weighted graph without self-loops and multiple edges is given. Graph contains n vertices and m edges.

    For each edge (u, v) find the minimal possible weight of the spanning tree that contains the edge (u, v).

    The weight of the spanning tree is the sum of weights of all edges included in spanning tree.

    Input

    First line contains two integers n and m (1 ≤ n ≤ 2·105, n - 1 ≤ m ≤ 2·105) — the number of vertices and edges in graph.

    Each of the next m lines contains three integers ui, vi, wi (1 ≤ ui, vi ≤ n, ui ≠ vi, 1 ≤ wi ≤ 109) — the endpoints of the i-th edge and its weight.

    Output

    Print m lines. i-th line should contain the minimal possible weight of the spanning tree that contains i-th edge.

    The edges are numbered from 1 to m in order of their appearing in input.

    Sample Input

    5 7

    1 2 3

    1 3 1

    1 4 5

    2 3 2

    2 5 3

    3 4 2

    4 5 4

    Sample Output

    9

    8

    11

    8

    8

    8

    9

    Hint

    题意

    给你一个图,n点m边。对于每个边,问你包含这条边的最小生成树是多少。

    题解:

    先生成一个最小生成树,加入一条边,可能会产生一个环,那么求这个环的最小值即可,

    这个用倍增就行,就和求次小生成树一模一样。

    今天typora终于可以用搜狗输入法了,我发现终端打开都用不了搜狗输入法,真奇怪呀。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define N 400050
    ll n,m;
    ll dp[N],mm[N],fu[N][21],mx[N][21];
    ll tot,last[N];
    struct Edge
    {
        ll from,to,val,s;
        bool operator < (const Edge&b)
            {return val<b.val;}
    }a[N],edges[N];
    template<typename T>void read(T&x)
    {
        ll k=0; char c=getchar();
        x=0;
        while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
        if (c==EOF)exit(0);
        while(isdigit(c))x=x*10+c-'0',c=getchar();
        x=k?-x:x;
    }
    void read_char(char &c)
    {while(!isalpha(c=getchar())&&c!=EOF);}
    void AddEdge(ll x,ll y,ll z)
    {
        edges[++tot]=Edge{x,y,z,last[x]};
        last[x]=tot;
    }
    ll gf(ll x,ll *f)
    {
        if (x==f[x])return x;
        return f[x]=gf(f[x],f);
    }
    ll MST(Edge *edges)
    {
        static ll f[N]; static Edge a[N];
        for(ll i=1;i<=m;i++)a[i]=edges[i];
        ll num=0,sum=0;
        sort(a+1,a+m+1);
        for(ll i=1;i<=n;i++)f[i]=i;
        for(ll i=1;i<=m;i++)
        {
            Edge e=a[i];//
            ll fx=gf(e.from,f),fy=gf(e.to,f);
            if (fx!=fy)//
    	{
                f[fx]=fy;
                num++;
                sum+=e.val;
                AddEdge(e.to,e.from,e.val);
                AddEdge(e.from,e.to,e.val);
    	}
            if (num==n-1)break;
        }
        return sum;
    }
    void dfs(ll x,ll pre)
    {
        dp[x]=dp[pre]+1;
        fu[x][0]=pre;
        for(ll i=last[x];i;i=edges[i].s)
        {
            Edge &e=edges[i];
            if (e.to==pre)continue;
            mx[e.to][0]=e.val;
            dfs(e.to,x);
        }
    }
    void init_ST(ll n)
    {
        mm[0]=-1;
        for(ll i=1;i<=n;i++) mm[i]=(i&(i-1))==0?mm[i-1]+1:mm[i-1];
        for(ll i=1;i<=20;i++)
            for(ll j=1;j<=n;j++)
            {
                fu[j][i]=fu[fu[j][i-1]][i-1];
                mx[j][i]=max(mx[j][i-1],mx[fu[j][i-1]][i-1]);
            }
    }
    ll get_max(ll x,ll y)
    {
        ll ans=0;
        if (dp[x]<dp[y])swap(x,y);
        for(ll i=mm[dp[x]-dp[y]];i>=0;i--)
            if (dp[fu[x][i]]>=dp[y])
            {
                ans=max(ans,mx[x][i]);
                x=fu[x][i];
            }
        if (x==y)return ans;
        for(ll i=mm[dp[x]-1];i>=0;i--)
            if (fu[x][i]!=fu[y][i])
            {
                ans=max(ans,mx[x][i]);
                ans=max(ans,mx[y][i]);
                x=fu[x][i];
                y=fu[y][i];
            }
        ans=max(ans,mx[x][0]);
        ans=max(ans,mx[y][0]);
        return ans;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("aa.in","r",stdin);
    #endif
        read(n); read(m);
        for(ll i=1;i<=m;i++)
        {
            ll x,y,z;
            read(x); read(y); read(z);
            a[i]=Edge{x,y,z,0};
        }
        ll sum=MST(a);
        dfs(1,0);
        init_ST(n);
        for(ll i=1;i<=m;i++)
        {
            ll ans=sum-get_max(a[i].from,a[i].to)+a[i].val;
            printf("%lld
    ",ans);
        }
    }
    
    
  • 相关阅读:
    经典算法之冒泡排序(Bubble Sort)-Python实现
    经典算法之快速排序(Quick Sort)-Python实现
    2020年SRE的随心感悟
    django: 像正常运行django的项目运行单个文件
    整理一下javascript中offsetWidth、clientWidth、width、scrollWidth、clientX、screenX、offsetX、pageX的具体含义
    requestAnimationFram 的优势及使用场景
    js 隐式数据转换带来的BUG
    为什么我不建议在js中使用链接变量分配
    关于JS函数传参的数据修改
    实现一个查看浏览器内核及版本号的功能函数
  • 原文地址:https://www.cnblogs.com/mmmqqdd/p/10828878.html
Copyright © 2011-2022 走看看