Shu-How Zの小窝

Loading...

Minimum spanning tree for each edge题解

原题在这里
题意:给定一张图,求:
对于每条边,求包含这条边的最小生成树的权值的和。
思路:
先把最小生成树算出来,对于每条边,如果这条边包含在最小生成树里,则不变。否则如果这条边的两个点是 xy ,那新的最小生成树一定是原来的最小生成树删去从 xy 的路径上全职最大的边再加上这条边的权值。而树上两点路径上的最大权值可以用 LCA 解决。
代码:

#include<bits/stdc++.h>
#define int long long
#define PII pair<int,int>
using namespace std;
const int N=2e5;
int n,m;
struct edge{
    int x,y,w,id;
}e[N+5];
vector<PII> v[N+5];
int sum=0;
int ans[N+5];

bool vis[N+5];
int pre[N+5];
int find(int x){return pre[x]==x?x:pre[x]=find(pre[x]);}
void Kruscal()
{
    for(int i=1;i<=n;i++) pre[i]=i;
    for(int i=1;i<=m;i++)
    {
        int fx=find(e[i].x);
        int fy=find(e[i].y);
        if(fx==fy) continue;
        sum+=e[i].w;
        vis[e[i].id]=1;
        pre[fx]=fy;
        v[e[i].x].push_back({e[i].y,e[i].w});
        v[e[i].y].push_back({e[i].x,e[i].w});
    }
}

int dep[N+5];
int lca[N+5][31];
int RMQ[N+5][31];
void dfs(int node,int father)
{
    dep[node]=dep[father]+1;
    lca[node][0]=father;
    for(int j=1;j<=30;j++)
    {
        lca[node][j]=lca[lca[node][j-1]][j-1];
        RMQ[node][j]=max(RMQ[node][j-1],RMQ[lca[node][j-1]][j-1]);
    }
    for(auto son:v[node])
    {
        if(son.first==father) continue;
        RMQ[son.first][0]=son.second;
        dfs(son.first,node);
    }
}
int query(int x,int y)
{
    if(dep[x]>dep[y]) swap(x,y);
    int res=0;
    for(int j=30;j>=0;j--)
    {
        if(dep[lca[y][j]]>=dep[x])
        {
            res=max(res,RMQ[y][j]);
            y=lca[y][j];
        }
    }
    if(x==y) return res;
    for(int j=30;j>=0;j--)
    {
        if(lca[x][j]!=lca[y][j])
        {
            res=max(res,max(RMQ[x][j],RMQ[y][j]));
            x=lca[x][j];
            y=lca[y][j];
        }
    }
    return max(res,max(RMQ[x][0],RMQ[y][0]));
}

bool cmp(edge a,edge b){return a.w<b.w;}
bool CMP(edge a,edge b){return a.id<b.id;}
signed main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>e[i].x>>e[i].y>>e[i].w;
        e[i].id=i;
    }
    stable_sort(e+1,e+m+1,cmp);
    Kruscal();
    dfs(1,0);
    stable_sort(e+1,e+m+1,CMP);
    for(int i=1;i<=m;i++)
    {
        cout<<sum-query(e[i].x,e[i].y)+e[i].w<<"\n";
    }
    return 0;
}
posted @   wangyanxiao  阅读(0)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示