【JZOJ4596】Stree

Description

给出n个点,m条有权边,现对于每一条边,你需要回答出包含这条边的最小生成树的总边权值。

原题在:CF609E

Solution

对原图做一遍最小生成树,那么在最小生成树上的边答案就是该最小生成树边权和。

原图没有重边,这说明任选 n1 条不构成环的边都可以构成生成树。

对于不在最小生成树上的边 (u,v) ,我们知道树中最短路径是唯一的,如果添加了 (u,v) ,那么就会生成环,这时我们只要删掉原最小生成树上的 u>v 路径上最大的边,就可以再次将原图变为包含 (u,v) 的最小生成树。

运用树上倍增算法可以达到 O(nlog2n)

Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 200001
#define M 400001
#define ll long long
using namespace std;
struct node{
    int u,v,w,t;
}b[N];
int f[N];
int wz[N];
ll c[N];
int to[M],next[M],last[M],val[M],num=0;
int fa[N][21],mx[N][21];
int d[N];
void link(int x,int y,int c)
{
    num++;
    to[num]=y;
    next[num]=last[x];
    last[x]=num;
    val[num]=c;
}
bool cmp(node x,node y)
{
    return x.w<y.w;
}
int find(int x)
{
    return !f[x]?x:f[x]=find(f[x]);
}
void dfs(int x)
{
    for(int i=last[x];i;i=next[i])
    {
        int v=to[i];
        if(v!=fa[x][0])
        {
            fa[v][0]=x;
            mx[v][0]=val[i];
            d[v]=d[x]+1;
            dfs(v);
        }
    }
}
int work(int x,int y)
{
    if(d[x]<d[y]) swap(x,y);
    int tmp=0;
    fd(i,20,0)
    if(fa[x][i] && d[fa[x][i]]>=d[y])
    tmp=max(tmp,mx[x][i]),x=fa[x][i];
    fd(i,20,0)
    if(fa[x][i]!=fa[y][i] && fa[x][i] && fa[y][i])
    {
        tmp=max(tmp,mx[x][i]);
        x=fa[x][i];
        tmp=max(tmp,mx[y][i]);
        y=fa[y][i];
    }
    if(x!=y)
    {
        tmp=max(tmp,mx[x][0]);
        tmp=max(tmp,mx[y][0]);
    }
    return tmp;
}
int main()
{
    freopen("street.in","r",stdin);
    freopen("street.out","w",stdout);
    int n,m;
    cin>>n>>m;
    fo(i,1,m)
    {
        scanf("%d %d %d",&b[i].u,&b[i].v,&b[i].w);
        b[i].t=i;
    }
    sort(b+1,b+m+1,cmp);
    fo(i,1,m) wz[b[i].t]=i;
    int z=0;
    ll tt=0;
    fo(i,1,m)
    {
        int fx=find(b[i].u),fy=find(b[i].v);
        if(fx!=fy)
        {
            link(b[i].u,b[i].v,b[i].w);
            link(b[i].v,b[i].u,b[i].w);
            f[fy]=fx;
            tt+=b[i].w;
            c[b[i].t]=-1;
            z++;
            if(z==n-1) break;
        }
    }
    fo(i,1,m)
    if(c[i]<0) c[i]=tt;
    d[0]=-1;
    dfs(1);
    fo(j,1,20)
    fo(i,1,n)
    {
        fa[i][j]=fa[fa[i][j-1]][j-1];
        mx[i][j]=max(mx[i][j-1],mx[fa[i][j-1]][j-1]);
    }
    fo(q,1,m)
    if(!c[q])
    {
        int u=b[wz[q]].u,v=b[wz[q]].v,w=b[wz[q]].w;
        int zz=work(u,v);
        c[q]=tt-zz+w;
    }
    fo(i,1,m) printf("%lld\n",c[i]);
}
posted @ 2016-07-08 16:06  sadstone  阅读(35)  评论(0编辑  收藏  举报