【CF 609E】Street

来源:互联网 发布:用友nc java版本win7 编辑:程序博客网 时间:2024/06/05 02:50

Description

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

Solution

有一道很像的题目电话线铺设,而且这题还比电话线铺设水很多。

观察数据

发现数据很大,又都在int范围内,还有求和求积之类的操作,就要开long long。

Code

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)#define rep(i,a) for(i=first[a];i;i=next[i])using namespace std;const int maxn=200007;int i,j,k,l,t,n,m,w,e,num,x,y,z;int fa[maxn],first[maxn*2],next[maxn*2],last[maxn*2],tot,chang[maxn*2];int f[maxn][20],g[maxn][20],aa;int deep[maxn];long long ans2,ans3[maxn];bool bz[maxn];struct node{    int x,y,z,d;}a[maxn];bool cmp(node x,node y){    return (x.z<y.z)||(x.z==y.z&&x.x<y.x)||(x.z==y.z&&x.x==y.x&&x.y<y.y);}int gf(int x){    if(!fa[x])return x;    fa[x]=gf(fa[x]);return fa[x];}void add(int x,int y,int z){    last[++tot]=y;    next[tot]=first[x];    first[x]=tot;    chang[tot]=z;    last[++tot]=x;    next[tot]=first[y];    first[y]=tot;    chang[tot]=z;}void dfs(int x,int y){    int i,j;    f[x][0]=y;deep[x]=deep[y]+1;    rep(i,x){        if(last[i]!=y)dfs(last[i],x),g[last[i]][0]=chang[i];    }}int lca(int x,int y){    int i,k=0;    if(deep[x]<deep[y])swap(x,y);    fod(i,19,0)if(deep[f[x][i]]>deep[y])k=max(k,g[x][i]),x=f[x][i];        if(deep[x]!=deep[y])k=max(k,g[x][0]),x=f[x][0];    fod(i,19,0)if(f[x][i]!=f[y][i])k=max(k,g[x][i]),k=max(k,g[y][i]),x=f[x][i],y=f[y][i];    if(x!=y)k=max(k,g[x][0]),k=max(k,g[y][0]);aa=k;    if(x!=y)return f[x][0];else return x;}int main(){    freopen("street.in","r",stdin);    freopen("street.out","w",stdout);    scanf("%d%d",&n,&w);    fo(i,1,w){        scanf("%d%d%d",&k,&t,&e);if(k>t)swap(k,t);        a[++num].x=k,a[num].y=t,a[num].z=e,a[num].d=i;    }    sort(a+1,a+1+num,cmp);    fo(i,1,num){        x=gf(a[i].x),y=gf(a[i].y);        if(x!=y){            fa[y]=x;m++;            ans2+=a[i].z;            bz[i]=1;            add(a[i].x,a[i].y,a[i].z);        }           if(m==n-1)break;    }    dfs(1,0);    fo(j,1,19)fo(i,1,n){        f[i][j]=f[f[i][j-1]][j-1];        if(f[i][j])g[i][j]=max(g[i][j-1],g[f[i][j-1]][j-1]);    }    fo(i,1,w){        if(bz[i]){            ans3[a[i].d]=ans2;            continue;        }        int o=lca(a[i].x,a[i].y);        ans3[a[i].d]=ans2+a[i].z-aa;    }    fo(i,1,w){        printf("%lld\n",ans3[i]);    }}
1 0
原创粉丝点击