E. Minimum spanning tree for each edge
time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

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.

Examples
input
5 7
1 2 3
1 3 1
1 4 5
2 3 2
2 5 3
3 4 2
4 5 4
output
9
8
11
8
8
8
9

题意:给你n个点,m条边;

   第i条为必选边,求最小的生成树;

思路:先建好一颗最小生成树,如果边在生成树上,输出最小的即可;

   对于不在树上的如何求解:

      原来建好的一棵树,再加入一条边,会使得形成一个环,去查找原来最小生成树中u到v最大的边权,最小生成树的权值减去最大的边权+当前的边权即使答案;

   无更新的区间最大值,可以用倍增的写法;

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define pi (4*atan(1.0))
#define eps 1e-4
#define bug(x) cout<<"bug"<<x<<endl;
const int N=2e5+,M=1e6+,inf=;
const ll INF=1e18+,mod=; ///数组大小
struct edge
{
int v,next;
} edge[N<<];
int head[N<<],edg,id,n;
/// 树链剖分 int fa[N],dep[N],son[N],siz[N]; // fa父亲,dep深度,son重儿子,siz以该点为子树的节点个数
int ran[N],top[N],tid[N],num[N]; // tid表示边的标号,top通过重边可以到达最上面的点,ran表示标记tid
void init()
{
memset(son,-,sizeof(son));
memset(head,-,sizeof(head));
edg=;
id=;
} void add(int u,int v)
{
edg++;
edge[edg].v=v;
edge[edg].next=head[u];
head[u]=edg;
} void dfs1(int u,int fath,int deep)
{
fa[u]=fath;
siz[u]=;
dep[u]=deep;
for(int i=head[u]; i!=-; i=edge[i].next)
{
int v=edge[i].v;
if(v==fath)continue;
dfs1(v,u,deep+);
siz[u]+=siz[v];
if(son[u]==-||siz[v]>siz[son[u]])
son[u]=v;
}
} void dfs2(int u,int tp)
{
tid[u]=++id;
top[u]=tp;
ran[tid[u]]=u;
if(son[u]==-)return;
dfs2(son[u],tp);
for(int i=head[u]; i!=-; i=edge[i].next)
{
int v=edge[i].v;
if(v==fa[u])continue;
if(v!=son[u])
dfs2(v,v);
}
} struct SGT
{
int maxx[N<<];
void pushup(int pos)
{
maxx[pos]=max(maxx[pos<<],maxx[pos<<|]);
}
void build(int l,int r,int pos)
{
if(l==r)
{
maxx[pos]=num[ran[l]];
return;
}
int mid=(l+r)>>;
build(l,mid,pos<<);
build(mid+,r,pos<<|);
pushup(pos);
}
int query(int L,int R,int l,int r,int pos)
{
//cout<<L<<" "<<R<<" "<<l<<" "<<r<<endl;
if(L<=l&&r<=R)return maxx[pos];
int mid=(l+r)>>;
int ans=;
if(L<=mid)ans=max(ans,query(L,R,l,mid,pos<<));
if(R>mid) ans=max(ans,query(L,R,mid+,r,pos<<|));
return ans;
}
}tree; int up(int l,int r)
{
int ans=;
while(top[l]!=top[r])
{
if(dep[top[l]]<dep[top[r]])swap(l,r); ans=max(ans,tree.query(tid[top[l]],tid[l],,n,));
l=fa[top[l]];
} if(dep[l]<dep[r])swap(l,r);
if(l==r)return ans;
ans=max(ans,tree.query(tid[son[r]],tid[l],,n,));
return ans;
}
/// 克鲁斯卡尔
struct is
{
int u,v,w,pos;
operator <(const is &x)const
{
return w<x.w;
}
}a[N];
int fafa[N],ans[N];
int Find(int x)
{
return x==fafa[x]?x:fafa[x]=Find(fafa[x]);
}
ll out[N];
int main()
{
init();
int m;
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w),a[i].pos=i;
sort(a+,a++m);
ll minn=;
for(int i=;i<=n;i++)
fafa[i]=i;
for(int i=;i<=m;i++)
{
int x=Find(a[i].u);
int y=Find(a[i].v);
if(x!=y)
{
add(a[i].u,a[i].v);
add(a[i].v,a[i].u);
fafa[x]=y;
minn+=a[i].w;
ans[i]=;
}
}
dfs1(,-,);
dfs2(,);
for(int i=;i<=m;i++)
{
if(ans[i])
{
if(fa[a[i].u]==a[i].v)
num[a[i].u]=a[i].w;
else
num[a[i].v]=a[i].w;
}
}
tree.build(,n,);
for(int i=;i<=m;i++)
{
if(ans[i])out[a[i].pos]=minn;
else
{
int x=up(a[i].u,a[i].v);
out[a[i].pos]=minn-x+a[i].w;
}
}
for(int i=;i<=m;i++)
printf("%lld\n",out[i]);
return ;
}

Educational Codeforces Round 3 E. Minimum spanning tree for each edge 最小生成树+树链剖分+线段树的更多相关文章

  1. Educational Codeforces Round 3 E. Minimum spanning tree for each edge (最小生成树+树链剖分)

    题目链接:http://codeforces.com/contest/609/problem/E 给你n个点,m条边. 问枚举每条边,问你加这条边的前提下组成生成树的权值最小的树的权值和是多少. 先求 ...

  2. CF Educational Codeforces Round 3 E. Minimum spanning tree for each edge 最小生成树变种

    题目链接:http://codeforces.com/problemset/problem/609/E 大致就是有一棵树,对于每一条边,询问包含这条边,最小的一个生成树的权值. 做法就是先求一次最小生 ...

  3. Codeforces Educational Codeforces Round 3 E. Minimum spanning tree for each edge LCA链上最大值

    E. Minimum spanning tree for each edge 题目连接: http://www.codeforces.com/contest/609/problem/E Descrip ...

  4. 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 Descrip ...

  5. Educational Codeforces Round 3 E. Minimum spanning tree for each edge LCA/(树链剖分+数据结构) + MST

    E. Minimum spanning tree for each edge   Connected undirected weighted graph without self-loops and ...

  6. CF# Educational Codeforces Round 3 E. Minimum spanning tree for each edge

    E. Minimum spanning tree for each edge time limit per test 2 seconds memory limit per test 256 megab ...

  7. Water Tree CodeForces 343D 树链剖分+线段树

    Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...

  8. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  9. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

随机推荐

  1. jpg、gif、png-8、png-24的区别

    一.gif格式的特点 1.透明性.gif是一种布尔透明类型,即它可以是全透明,也可以是全不透明,但是没有半透明 2.动画.gif支持动画 3.无损耗性.gif是一种无损耗的图像格式,这意味着你可以对g ...

  2. The Little Prince-12/13

    The Little Prince-12/13 突然发现:这应该是一封情书~ 我那时什么也不懂!我应该根据她的行为,而不是根据她的话来判断她. 她使我的生活芬芳多彩,我真不该离开她跑出来.我本应该猜出 ...

  3. right spindle supply short to gnd-- compact version

    hardware guy found that the R1004 lead to this error, but this error should not be checked, because ...

  4. Caused by: java.lang.ClassNotFoundException: Illegal access: this web application instance has been stopped already. Could not load [org.jboss.netty.util.internal.ByteBufferUtil]. The following stack

    Caused by: java.lang.ClassNotFoundException: Illegal access: this web application instance has been ...

  5. if语法

    语法一: if 条件:   条件成立时执行的子代码块 age_of_girl=31 if age_of_girl > 30: print('阿姨好') 语法二:if + else   if 条件 ...

  6. ELK学习笔记之Grok patterns正则匹配

    https://github.com/logstash-plugins/logstash-patterns-core/blob/master/patterns/grok-patterns USERNA ...

  7. android之发送Get或Post请求至服务器接口

    import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; imp ...

  8. Android之RadioButton多行

    RadioGroup设置orientation="vertical"竖向单列显示 RadioGroup设置orientation="horizontal"横向单 ...

  9. JAVA基础部分 JDK和JRE以及JVM

    第一部分: 一.dos命令 *快捷查看电脑ip: Win + R进入cmd;输入ipconfig/all查看IPv4:192.168.0.xxx(首选); 基本命令: cd进入目录:d: 直接进入盘符 ...

  10. Python中的对象行为与特殊方法(一)对象的创建与销毁

    Python中类调用__new__()类方法来创建实例,调用__init__()方法来初始化对象,对象的销毁则调用__del__()方法. __new__()方法第一个参数为类cls,通常返回cls的 ...