Minimum spanning tree for each edge CodeForces - 609E (Lca+最小生成树)
2018-03-22 15:42
513 查看
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.
InputFirst 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.
OutputPrint 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.
ExampleInput
#include<string>
#include<algorithm>
#include<vector>
#include<cmath>
#define bug(x) printf("%d*****\n",x)
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
struct Edge{
int u,v;
ll w;
int id,flag;
Edge(){}
Edge(int _u,int _v,ll _w,int _id):u(_u),v(_v),w(_w),id(_id){}
}edge[maxn];
struct Node{
int v;
ll w;
Node(){}
Node(int _v,ll _w):v(_v),w(_w){}
}now;
vector<Node> vec[maxn];
int dep[maxn],rt[maxn][20],pre[maxn];
ll dis[maxn],Max[maxn][20];
int n,m;
int find_rt(int x){
return pre[x]==x?x:pre[x]=find_rt(pre[x]);
}
ll get_tree(){
ll ans=0;
int cnt=0;
for(int i=1;i<=n;i++) pre[i]=i;
for(int i=1;i<=m;i++){
int u=edge[i].u,v=edge[i].v;
ll w=edge[i].w;
int ru=find_rt(u),rv=find_rt(v);
if(ru!=rv){
ans+=edge[i].w;
edge[i].flag=1;
pre[ru]=rv;
cnt++;
now=Node(v,w);
vec[u].push_back(now);
now=Node(u,w);
vec[v].push_back(now);
//printf("u:%d v:%d w:%lld\n",u,v,w);
if(cnt+1==n) break;
}
}
return ans;
}
int cmp1(Edge a,Edge b){
return a.w<b.w;
}
int cmp2(Edge a,Edge b){
return a.id<b.id;
}
int vis[maxn];
void dfs(int u){
vis[u]=1;
//printf("u:%d\n",u);
for(int i=0;i<vec[u].size();i++){
int v=vec[u][i].v;
ll w=vec[u][i].w;
if(!vis[v]) {
rt[v][0]=u;
dis[v]=dis[u]+w;
dep[v]=dep[u]+1;
Max[v][0]=w;
dfs(v);
}
}
}
void get_rt(){
for(int i=1;(1<<i)<=n;i++){
for(int j=1;j<=n;j++){
rt[j][i]=rt[rt[j][i-1]][i-1];
Max[j][i]=max(Max[j][i-1],Max[rt[j][i-1]][i-1]);
// printf("i:%d j:%d maxw:%lld\n",i,j,Max[j][i]);
}
}
}
int get_lca(int u,int v,ll& ans){
if(dep[u]>dep[v]) swap(u,v);
int dif=dep[v]-dep[u];
ll tmp1=0,tmp2=0;
for(int i=0;(1<<i)<=dif;i++){
if(dif&(1<<i)){
tmp2=max(tmp2,Max[v][i]);
v=rt[v][i];
// printf("v:%d tmp2:%lld i:%d\n",v,tmp2,i);
}
}
// printf("u:%d v:%d tmp2:%lld ",u,v,tmp2);
if(u!=v){
for(int i=(int)log2(n);i>=0;i--){
if(rt[u][i]!=rt[v][i]){
tmp1=max(tmp1,Max[u][i]);
tmp2=max(tmp2,Max[v][i]);
u=rt[u][i],v=rt[v][i];
}
}
tmp1=max(tmp1,Max[u][0]);
tmp2=max(tmp2,Max[v][0]);
u=rt[u][0];
}
ans=max(tmp1,tmp2);
// printf(" %lld\n",ans);
return u;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;ll w;
scanf("%d %d %lld",&u,&v,&w);
edge[i]=Edge(u,v,w,i);
edge[i].flag=0;
/* 在这里赋值,对于边来说没哟什么用,只能是做错
now=Node(v,w);
vec[u].push_back(now);
now=Node(u,w);
vec[v].push_back(now);
*/
}
ll sum=0;
sort(edge+1,edge+m+1,cmp1);
sum=get_tree();
sort(edge+1,edge+m+1,cmp2);
dis[1]=dep[1]=0;
dfs(1);
// printf("sum:%lld\n",sum);
get_rt();
for(int i=1;i<=m;i++){
int u=edge[i].u,v=edge[i].v;
if(edge[i].flag){
printf("%lld\n",sum);
continue;
}
ll ans;
int r=get_lca(u,v,ans);
// printf("u:%d v:%d r:%d ans:%lld\n",u,v,r,ans);
printf("%lld\n",sum+edge[i].w-ans);
}
return 0;
}
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.
InputFirst 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.
OutputPrint 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.
ExampleInput
5 7 1 2 3 1 3 1 1 4 5 2 3 2 2 5 3 3 4 2 4 5 4Output
9 8 11 8 8 8 9#include<cstdio>
#include<string>
#include<algorithm>
#include<vector>
#include<cmath>
#define bug(x) printf("%d*****\n",x)
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
struct Edge{
int u,v;
ll w;
int id,flag;
Edge(){}
Edge(int _u,int _v,ll _w,int _id):u(_u),v(_v),w(_w),id(_id){}
}edge[maxn];
struct Node{
int v;
ll w;
Node(){}
Node(int _v,ll _w):v(_v),w(_w){}
}now;
vector<Node> vec[maxn];
int dep[maxn],rt[maxn][20],pre[maxn];
ll dis[maxn],Max[maxn][20];
int n,m;
int find_rt(int x){
return pre[x]==x?x:pre[x]=find_rt(pre[x]);
}
ll get_tree(){
ll ans=0;
int cnt=0;
for(int i=1;i<=n;i++) pre[i]=i;
for(int i=1;i<=m;i++){
int u=edge[i].u,v=edge[i].v;
ll w=edge[i].w;
int ru=find_rt(u),rv=find_rt(v);
if(ru!=rv){
ans+=edge[i].w;
edge[i].flag=1;
pre[ru]=rv;
cnt++;
now=Node(v,w);
vec[u].push_back(now);
now=Node(u,w);
vec[v].push_back(now);
//printf("u:%d v:%d w:%lld\n",u,v,w);
if(cnt+1==n) break;
}
}
return ans;
}
int cmp1(Edge a,Edge b){
return a.w<b.w;
}
int cmp2(Edge a,Edge b){
return a.id<b.id;
}
int vis[maxn];
void dfs(int u){
vis[u]=1;
//printf("u:%d\n",u);
for(int i=0;i<vec[u].size();i++){
int v=vec[u][i].v;
ll w=vec[u][i].w;
if(!vis[v]) {
rt[v][0]=u;
dis[v]=dis[u]+w;
dep[v]=dep[u]+1;
Max[v][0]=w;
dfs(v);
}
}
}
void get_rt(){
for(int i=1;(1<<i)<=n;i++){
for(int j=1;j<=n;j++){
rt[j][i]=rt[rt[j][i-1]][i-1];
Max[j][i]=max(Max[j][i-1],Max[rt[j][i-1]][i-1]);
// printf("i:%d j:%d maxw:%lld\n",i,j,Max[j][i]);
}
}
}
int get_lca(int u,int v,ll& ans){
if(dep[u]>dep[v]) swap(u,v);
int dif=dep[v]-dep[u];
ll tmp1=0,tmp2=0;
for(int i=0;(1<<i)<=dif;i++){
if(dif&(1<<i)){
tmp2=max(tmp2,Max[v][i]);
v=rt[v][i];
// printf("v:%d tmp2:%lld i:%d\n",v,tmp2,i);
}
}
// printf("u:%d v:%d tmp2:%lld ",u,v,tmp2);
if(u!=v){
for(int i=(int)log2(n);i>=0;i--){
if(rt[u][i]!=rt[v][i]){
tmp1=max(tmp1,Max[u][i]);
tmp2=max(tmp2,Max[v][i]);
u=rt[u][i],v=rt[v][i];
}
}
tmp1=max(tmp1,Max[u][0]);
tmp2=max(tmp2,Max[v][0]);
u=rt[u][0];
}
ans=max(tmp1,tmp2);
// printf(" %lld\n",ans);
return u;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;ll w;
scanf("%d %d %lld",&u,&v,&w);
edge[i]=Edge(u,v,w,i);
edge[i].flag=0;
/* 在这里赋值,对于边来说没哟什么用,只能是做错
now=Node(v,w);
vec[u].push_back(now);
now=Node(u,w);
vec[v].push_back(now);
*/
}
ll sum=0;
sort(edge+1,edge+m+1,cmp1);
sum=get_tree();
sort(edge+1,edge+m+1,cmp2);
dis[1]=dep[1]=0;
dfs(1);
// printf("sum:%lld\n",sum);
get_rt();
for(int i=1;i<=m;i++){
int u=edge[i].u,v=edge[i].v;
if(edge[i].flag){
printf("%lld\n",sum);
continue;
}
ll ans;
int r=get_lca(u,v,ans);
// printf("u:%d v:%d r:%d ans:%lld\n",u,v,r,ans);
printf("%lld\n",sum+edge[i].w-ans);
}
return 0;
}
相关文章推荐
- Minimum spanning tree for each edge CodeForces - 609E(ST算法+树链剖分(或倍增LCA)+最小生成树)
- Educational Codeforces Round 3 E. Minimum spanning tree for each edge 最小生成树+树链剖分+线段树
- 【Educational Codeforces Round 3 E】【树链剖分】Minimum spanning tree for each edge 图构最小生成树,生成树必须包含第i条边
- Minimum spanning tree for each edge CodeForces - 609E
- Educational Codeforces Round 3 E (609E) Minimum spanning tree for each edge
- Educational Codeforces Round 3 E. Minimum spanning tree for each edge LCA/(树链剖分+数据结构) + MST
- 文章标题 coderforces 609E : Minimum spanning tree for each edge (MST+LCA)
- CodeForces 609 E.Minimum spanning tree for each edge(最小生成树-Kruskal+在线倍增LCA)
- CF# Educational Codeforces Round 3 E. Minimum spanning tree for each edge
- Educational Codeforces Round 3 E. Minimum spanning tree for each edge MST+树上路径倍增
- 609E - Minimum spanning tree for each edge
- Codeforces Edu3 E. Minimum spanning tree for each edge
- E - Minimum spanning tree for each edge
- Codeforces Round #423 (Div. 1, rated, based on VK Cup Finals) D. Best Edge Weight(最小生成树+LCA+树链剖分)
- 说说最小生成树(Minimum Spanning Tree)
- Another Minimum Spanning Tree - UVaLive 3662 曼哈顿最小生成树
- 说说最小生成树(Minimum Spanning Tree)
- Union Find 在 最小生成树(Minimum Spanning Tree)中的实现
- MST(Minimum Spanning Tree,最小生成树)
- 最小生成树(Minimum Spanning Tree)