题意:一个无向图联通中,求包含每条边的最小生成树的值(无自环,无重边)

分析:求出这个图的最小生成树,用最小生成树上的边建图

对于每条边,不外乎两种情况

1:该边就是最小生成树上的边,那么答案显然

2:该边不在最小生成树上,那么进行路径查询,假设加入这条边,那么形成一个环,删去这个环上除该边外的最大权值边,形成一棵树

树的权值即为答案。(并不需要真正加入这条边)

注:其实用树链剖分和LCA都可以,选择自己熟悉的写就行,我写的树链剖分

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long LL;
const int maxn=;
int n,m;
LL mst;
struct Edge
{
int w,v,next;
} edge[maxn<<];
struct E
{
int u,v,w,id,mark;
void init(int a,int b,int c,int d)
{
u=a,v=b,w=c,id=d,mark=;
}
} o[maxn];
bool cmp1(E a,E b)
{
return a.id<b.id;
}
bool cmp2(E a,E b)
{
return a.w<b.w;
}
int head[maxn],p;
void addedge(int u,int v,int w)
{
edge[p].v=v;
edge[p].w=w;
edge[p].next=head[u];
head[u]=p++;
}
int fa[maxn],sz[maxn],id[maxn],dep[maxn],top[maxn],son[maxn],clk;
int ww[maxn],re[maxn];
void dfs1(int u,int f,int d)
{
fa[u]=f;
sz[u]=;
son[u]=-;
dep[u]=d;
for(int i=head[u]; ~i; i=edge[i].next)
{
int v=edge[i].v;
if(v==f)continue;
dfs1(v,u,d+);
sz[u]+=sz[v];
if(son[u]==-||sz[v]>sz[son[u]])
son[u]=v,re[u]=edge[i].w;
}
}
void dfs2(int u,int tp,int cc)
{
id[u]=++clk;
top[u]=tp;
ww[id[u]]=cc;
if(son[u]!=-)dfs2(son[u],tp,re[u]);
for(int i=head[u]; ~i; i=edge[i].next)
{
int v=edge[i].v;
if(v==son[u]||v==fa[u])continue;
dfs2(v,v,edge[i].w);
}
}
int maxw[maxn<<];
void pushup(int rt)
{
maxw[rt]=max(maxw[rt*],maxw[rt*+]);
}
void build(int rt,int l,int r)
{
if(l==r)
{
maxw[rt]=ww[l];
return;
}
int m=(l+r)>>;
build(rt*,l,m);
build(rt*+,m+,r);
pushup(rt);
}
int query(int rt,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
return maxw[rt];
int m=(l+r)>>;
int ans=-;
if(x<=m)ans=max(ans,query(rt*,l,m,x,y));
if(y>m)ans=max(ans,query(rt*+,m+,r,x,y));
return ans;
}
int getans(int u,int v)
{
int ans=-;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])swap(u,v);
ans=max(ans,query(,,n,id[top[u]],id[u]));
u=fa[top[u]];
}
if(dep[u]>dep[v])swap(u,v);
ans=max(ans,query(,,n,id[son[u]],id[v]));
return ans;
}
int fat[maxn];
int find(int x)
{
if(x==fat[x])return x;
return fat[x]=find(fat[x]);
}
void init()
{
for(int i=; i<=n; ++i)
fat[i]=i;
mst=p=clk=;
memset(head,-,sizeof(head));
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
for(int i=; i<m; ++i)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
o[i].init(u,v,w,i);
}
sort(o,o+m,cmp2);
int cnt=;
for(int i=; i<m; ++i)
{
int fx=find(o[i].u);
int fy=find(o[i].v);
if(fy==fx)continue;
addedge(o[i].u,o[i].v,o[i].w);
addedge(o[i].v,o[i].u,o[i].w);
cnt++;
o[i].mark=;
fat[fy]=fx;
mst+=o[i].w;
if(cnt>=n-)break;
}
dfs1(,-,);
dfs2(,,);
build(,,n);
sort(o,o+m,cmp1);
for(int i=; i<m; ++i)
{
if(o[i].mark)printf("%I64d\n",mst);
else
{
int tt=getans(o[i].u,o[i].v);
printf("%I64d\n",mst-tt+o[i].w);
}
}
}
return ;
}

Educational Codeforces Round 3 E (609E) Minimum spanning tree for each edge的更多相关文章

  1. [Educational Round 3][Codeforces 609E. Minimum spanning tree for each edge]

    这题本来是想放在educational round 3的题解里的,但觉得很有意思就单独拿出来写了 题目链接:609E - Minimum spanning tree for each edge 题目大 ...

  2. codeforces 609E 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 ...

  3. codeforces 609E. Minimum spanning tree for each edge 树链剖分

    题目链接 给一个n个节点m条边的树, 每条边有权值, 输出m个数, 每个数代表包含这条边的最小生成树的值. 先将最小生成树求出来, 把树边都标记. 然后对标记的边的两个端点, 我们add(u, v), ...

  4. cf 609E.Minimum spanning tree for each edge

    最小生成树,lca(树链剖分(太难搞,不会写)) 问存在这条边的最小生成树,2种情况.1.这条边在原始最小生成树上.2.加上这条半形成一个环(加上),那么就找原来这条边2端点间的最大边就好(减去).( ...

  5. 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 ...

  6. 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 ...

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

  8. 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 ...

  9. 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 ...

随机推荐

  1. linux驱动系列之s3c2440内存布局

    刚开始学习linux在2440上面 linux内核分配标志可以分为三类:行为修饰符.区修饰符.类型. 区修饰符表示从哪儿分配内存,内核把物理内存分为多个区,每个区用于不同的目的. 内存中缓冲区存在的原 ...

  2. centos7 下手动安装MySQL-5.6.32-1.linux_glibc2.5.x86_64.rpm-bundle

    由于centos7默认不再是mysql数据库,所以度算手动安装一个. 全程参考http://www.2cto.com/database/201501/371451.html 这里摘抄以下这个链接的内容 ...

  3. onClick(View) of type new View.OnClickListener(){} must override a superclass method

    原地址:http://blog.csdn.net/aeolus1019/article/details/8014798 Android开发过程中代码错误报错如下: - implements andro ...

  4. C++11 FAQ中文版--转

    更新至英文版October 3, 2012 译者前言: 经过C++标准委员会的不懈努力,最新的ISO C++标准C++11,也即是原来的C++0x,已经正式发布了.让我们欢迎C++11! 今天获得St ...

  5. POJ2349+prim

    最小生成树 /* prim 题意:给定一些点,一些卫星,一个卫星能连接两个点,点和点之间通信有一定的距离限制. 问能使得所有的点联通的最小距离. */ #include<stdio.h> ...

  6. android 从系统相册获取一张图片

    package net.viralpatel.android.imagegalleray; import android.app.Activity; import android.content.In ...

  7. cocos2d-x 扩充引擎基类功能 引起的头文件重复包含问题的分析

    c++ 头文件包含 原因的分析:   c++  头文件的循环引用是指: .h 里面的里面的头文件的相互包含的,引起的重复引用的问题.cpp 里面包含头文件是不存在重复引用的问题(因为CPP没有#ifn ...

  8. jQuery 的 $("someobjectid”).event() 的绑定

    经验证,jquery 的 $("someobjectid”).event()事件绑定,如果放在某个会被重新初始化的对象里,就会被多次绑定. 如下 <div id="divID ...

  9. “段寄存器”的故事[转](彻底搞清内存段/elf段/实模式保护模式以及段寄存器)

    http://blog.csdn.net/michael2012zhao/article/details/5554023 一. 段寄存器的产生 段寄存器的产生源于Intel 8086 CPU体系结构中 ...

  10. 散列表 (Hash table,也叫哈希表)

    散列表是根据关键字(Key value)而直接访问在内存存储位置的数据结构.也就是说,它通过把键值通过一个函数的计算,映射到表中一个位置来访问记录,这加快了查找速度.这个映射函数称做散列函数,存放记录 ...